@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方法呼叫.