文章目錄
基於Java的配置元數據
有了基於XML的配置元數據和基於註解的配置元數據(還是依賴XML,需要配置容器掃描的包,以至於能夠找到註解),再來了解一種脫離XML的形式,Java-based
用配置類代替XML
配置類和普通的Java類一樣,區別在於配置類被一些註解標註。
舉例:
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
@Bean
可以看到,在配置類Appconfig中有一個被@Bean
標註的方法,這個方法返回一個實際類型爲MyServiceImpl
的對象。
這個配置等價於:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
細節:關於bean的id以及bean的類型
通過對照發現,缺省@Bean的屬性時,默認使用被@Bean修飾的方法的名稱,作爲bean的id
基於XML配置時,class指定bean的實際類型(通過反射機制創建對象);在基於Java的配置中,方法中的new MyseviceImpl()
就相當於指定了class屬性。
AnnotationConfigApplicationContext(Class<?>…)
請注意,由於使用了基於Java的配置,所以不能使用基於XML的構造器來構建容器,因此引入基於Java配置類的的構造器,通過這個方法加載配置類。
@Configuration
這個註解的作用是標註一個類是配置類,在包掃描的時候,讓容器“知道”這個類是一個配置元數據,從而加載到容器中。
注意上面的例子,並沒有在AppConfig這個配置類上加上@Configuration
註解,因爲加載配置元數據的方式是直接傳入構造器,而不是通過包掃描。(關於怎樣配置包掃描路徑,下面在介紹)
兼容基於註解的配置元數據 @ComponentScan
在介紹基於註解的配置時,特別強調XML中要配置包掃描路徑。因爲當時使用基於註解的配置時,構建容器時,傳入的參數是XML文件,所以必須告訴容器到“哪些”包下去“找”註解。
現在,基於Java的配置,不再使用XML,因此,對於包掃描的標籤,也需要使用註解的方式替換:@ComponentScan(basePackages = "org.example")
等價於<context:component-scan base-package="org.example"/>
改變bean的Scope:@Scope
在之前討論@Bean註解的時候,爲了避免對各種標籤的混淆,所以刻意的跳過了關於bean的Scope配置的問題。再來看上面的配置:
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
注意,這裏沒有指定myService
這個bean的Scope(默認爲Singleton),因爲兼容基於註解的配置,所以可以使用@Scope來指定bean的Scope
public class AppConfig {
@Bean
@Scope("prototype")
public MyService myService() {
return new MyServiceImpl();
}
}
再談@ComponentScan和@Configuration
在掃描包時,如果發現有類被@Configuration標註,容器就會將它當作配置類加載。
如果直接將某個類傳遞給構建容器的構造器,這個類即使不被Configuration標註,它也是被當作配置類加載。
最後再強調一點,僅有被@Bean修飾的方法,纔會產生bean,否則,容器會把他當作普通方法,而不是去創建一個默認名字爲方法名的bean