Spring註解編程(二)---@Configuration&@Bean 原

從Spring3.0,@Configuration用於定義配置類,可替換xml配置文件,被註解的類內部包含有一個或多個被@Bean註解的方法,這些方法將會被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext類進行掃描,並用於構建bean定義,初始化Spring容器。

1.@Configuration的定義

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

   /**
    * Explicitly specify the name of the Spring bean definition associated
    * with this Configuration class. If left unspecified (the common case),
    * a bean name will be automatically generated.
    * <p>The custom name applies only if the Configuration class is picked up via
    * component scanning or supplied directly to a {@link AnnotationConfigApplicationContext}.
    * If the Configuration class is registered as a traditional XML bean definition,
    * the name/id of the bean element will take precedence.
    * @return the specified bean name, if any
    * @see org.springframework.beans.factory.support.DefaultBeanNameGenerator
    */
   String value() default "";

}

注意:@Configuration註解的配置類有如下要求:

@Configuration不可以是final類型;
@Configuration不可以是匿名類;
嵌套的configuration必須是靜態類。

2.@Configuation+@Bean註冊Bean

@Configuration標註在類上,相當於把該類作爲spring的xml配置文件中的<beans>,作用爲:配置spring容器(應用上下文)

//配置類==配置文件
@Configuration  //告訴Spring這是一個配置類
public class MainConfig {

   //給容器中註冊一個Bean;類型爲返回值的類型,id默認是用方法名作爲id
   @Bean
   public Person person(){
      return new Person("lisi", 20);
   }

}

主方法進行測試:

public class MainTest {
   
   @SuppressWarnings("resource")
   public static void main(String[] args) {
      ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
      Person bean = applicationContext.getBean(Person.class);
      System.out.println(bean);
   
   }

}

@Bean下管理bean的生命週期

可以使用基於 Java 的配置來管理 bean 的生命週期。

1)@Bean 支持兩種屬性,即 initMethod 和destroyMethod,這些屬性可用於定義生命週期方法。在實例化 bean 或即將銷燬它時,容器便可調用生命週期方法。生命週期方法也稱爲回調方法,因爲它將由容器調用。

@Configuration
public class MainConfigOfLifeCycle {
   
   //@Scope("prototype")
   @Bean(initMethod="init",destroyMethod="detory")
   public Car car(){
      return new Car();
   }

}
public class Car {
   
   public Car(){
      System.out.println("car constructor...");
   }
   
   public void init(){
      System.out.println("car ... init...");
   }
   
   public void detory(){
      System.out.println("car ... detory...");
   }

}

2)通過讓Bean實現InitializingBean(定義初始化邏輯),DisposableBean(定義銷燬邏輯);

@Component
public class Cat implements InitializingBean,DisposableBean {

   public Cat(){
      System.out.println("cat constructor...");
   }

   //銷燬方法
   public void destroy() throws Exception {
      // TODO Auto-generated method stub
      System.out.println("cat...destroy...");
   }

   // 初始化方法
   public void afterPropertiesSet() throws Exception {
      // TODO Auto-generated method stub
      System.out.println("cat...afterPropertiesSet...");
   }

}

 3)@Bean 註釋註冊的 bean 也支持 JSR-250 規定的標準 @PostConstruct 和 @PreDestroy 註釋。

@PostConstruct    在bean創建完成並且屬性賦值完成;來執行初始化方法

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

@PreDestroy:在容器銷燬bean之前通知我們進行清理工作

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}
@Component
public class Dog {


   public Dog(){
      System.out.println("dog constructor...");
   }

   //對象創建並賦值之後調用
   @PostConstruct
   public void init(){
      System.out.println("Dog....@PostConstruct...");
   }

   //容器移除對象之前
   @PreDestroy
   public void detory(){
      System.out.println("Dog....@PreDestroy...");
   }

}

4)bean的後置處理器:實現BeanPostProcessor接口是在bean初始化前後進行一些處理工作,返回值是即將用到的bean,可以是原來的bean也可以是包裝後的bean

public interface BeanPostProcessor {
    //在初始化之前工作
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
    //在初始化之後工作
    Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}

示例

/**
 * 後置處理器:初始化前後進行處理工作
 * 將後置處理器加入到容器中
 * @author lpf
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      // TODO Auto-generated method stub
      System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
      return bean;
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      // TODO Auto-generated method stub
      System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
      return bean;
   }

}
    * BeanPostProcessor原理
    * populateBean(beanName, mbd, instanceWrapper);給bean進行屬性賦值
    * initializeBean
    * {
    * applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    * invokeInitMethods(beanName, wrappedBean, mbd);執行自定義初始化
    * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    *}
* Spring底層對 BeanPostProcessor 的使用;
* 我們最熟悉的XXXAware接口 就是通過ApplicationContextAwareProcessor後置處理器來實現的
* 還有bean賦值,注入其他組件,@Autowired,生命週期註解功能,@Async,xxx BeanPostProcessor;

 

3.@Configuration啓動容器+@Component註冊Bean

@Component
public class Car {
   
   public Car(){
      System.out.println("car constructor...");
   }
   
   public void init(){
      System.out.println("car ... init...");
   }
   
   public void detory(){
      System.out.println("car ... detory...");
   }

}

配置類

//添加自動掃描註解,basePackages爲Car包路徑
@ComponentScan("com.lemon.bean")
@Configuration
public class MainConfigOfLifeCycle {

   @Scope("prototype")
   @Bean(initMethod="init",destroyMethod="detory")
   public Car car(){
      return new Car();
   }

}

4.@Configuation總結


     @Configuation等價於<Beans></Beans>

     @Bean等價於<Bean></Bean>

     @ComponentScan等價於<context:component-scan base-package="com.lemon.bean"/>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章