@Bean 註解

sc_ik發表於2019-01-19

@Configuration 以及其中的 @Bean 註解

@Configuration 註解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    String value() default "";
}

從定義來看, @Configuration 註解是用 @Component 註解的, 因此 <context:component-scan/> 或者 @ComponentScan 都能處理 @Configuration 註解的類.

@Configuration 註解的類中可以宣告一個或多個 @Bean 註解的方法. 並且可以由 Spring 容器幫我們管理.

 @Configuration
 public class AppConfig {

     @Bean
     public MyBean myBean() {
         // instantiate, configure and return bean ...
     }
 }

userInfo() 方法可以直接呼叫同一類中的其他 @Bean 方法來引用它們. 這也說明這種方式使用的是同一個 bean.

@Configuration
public class MyBeanConfig {

    @Bean
    public Country country(){
        return new Country();
    }

    @Bean
    public UserInfo userInfo(){
        return new UserInfo(country());
    }

}

注: 在執行時對每個這樣的配置類(@Configuration)進行CGLIB子類化. 因此 @Configuration 類及其工廠方法不能標記為 final 或 private.

@Configuration 標記的類必須符合下面的要求:

  • 配置類必須以類的形式提供(不能是工廠方法返回的例項), 允許通過生成子類在執行時增強 (cglib 動態代理).
  • 配置類不能是 final 類 (沒法動態代理).
  • 配置類必須是非本地的 (即不能在方法中宣告)
  • 任何巢狀配置類都必須宣告為static。
  • @Bean 方法可能不會反過來建立進一步的配置類 (也就是返回的 bean 如果帶有 @Configuration, 也不會被特殊處理, 只會作為普通的 bean).

@Bean Lite Mode

@Bean 註解也可以在沒有使用 @Configuration 註解的類中宣告. 例如, 可以在 @Component 類中宣告, 甚至可以在普通的舊類中宣告. 在這種情況下, @Bean方法將以所謂的“lite”模式進行處理.

 @Component
 public class Calculator {
     public int sum(int a, int b) {
         return a+b;
     }

     @Bean
     public MyBean myBean() {
         return new MyBean();
     }
 }

@Configuration 中的 bean 是相反的, 當一個 @Bean 方法在lite模式下呼叫另一個 @Bean 方法時, 呼叫是標準的Java方法呼叫; Spring不會通過CGLIB代理攔截呼叫.

 @Component
public class MyBeanConfig {

    @Bean
    public Country country(){
        return new Country();
    }

    @Bean
    public UserInfo userInfo(){
        return new UserInfo(country());
    }

}

在lite模式下每執行一次 new UserInfo(country()); 都會建立一個新的 Country 物件, 這就是上面所說標準的Java方法呼叫.

相關文章