概述java
註釋配置相對於 XML 配置具備不少的優點:程序員
所以在不少狀況下,註釋配置比 XML 配置更受歡迎,註釋配置有進一步流行的趨勢。spring 2.5 的一大加強就是引入了不少註釋類,如今您已經可使用註釋配置完成大部分 XML 配置的功能。在這篇文章裏,咱們將向您講述使用註釋進行 Bean 定義和依賴注入的內容。正則表達式
原來咱們是怎麼作的spring
在使用註釋配置以前,先來回顧一下傳統上是如何配置 Bean 並完成 Bean 之間依賴關係的創建。下面是 3 個類,它們分別是 Office、Car 和 Boss,這 3 個類須要在 Spring 容器中配置爲 Bean:express
Office 僅有一個屬性:框架
清單 1. Office.javaide
package com.baobaotao; public class Office { private String officeNo =」001」; //省略 get/setter @Override public String toString() { return "officeNo:" + officeNo; } } |
Car 擁有兩個屬性:函數
清單 2. Car.javapost
package com.baobaotao; public class Car { private String brand; private double price; // 省略 get/setter @Override public String toString() { return "brand:" + brand + "," + "price:" + price; } } |
Boss 擁有 Office 和 Car 類型的兩個屬性:測試
清單 3. Boss.java
package com.baobaotao; public class Boss { private Car car; private Office office; // 省略 get/setter @Override public String toString() { return "car:" + car + "\n" + "office:" + office; } } |
咱們在 Spring 容器中將 Office 和 Car 聲明爲 Bean,並注入到 Boss Bean 中:下面是使用傳統 XML 完成這個工做的配置文件 beans.xml:
清單 4. beans.xml 將以上三個類配置成 Bean
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="boss" class="com.baobaotao.Boss"> <property name="car" ref="car"/> <property name="office" ref="office" /> </bean> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="002"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" 紅旗 CA72"/> <property name="price" value="2000"/> </bean> </beans> |
當咱們運行如下代碼時,控制檯將正確打出 boss 的信息:
清單 5. 測試類:AnnoIoCTest.java
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AnnoIoCTest { public static void main(String[] args) { String[] locations = {"beans.xml"}; ApplicationContext ctx = new ClassPathXmlApplicationContext(locations); Boss boss = (Boss) ctx.getBean("boss"); System.out.println(boss); } } |
這說明 Spring 容器已經正確完成了 Bean 建立和裝配的工做。
使用 @Autowired 註釋
Spring 2.5 引入了 @Autowired
註釋,它能夠對類成員變量、方法及構造函數進行標註,完成自動裝配的工做。來看一下使用@Autowired
進行成員變量自動注入的代碼:
清單 6. 使用 @Autowired 註釋的 Boss.java
package com.baobaotao; import org.springframework.beans.factory.annotation.Autowired; public class Boss { @Autowired private Car car; @Autowired private Office office; … } |
Spring 經過一個 BeanPostProcessor
對 @Autowired
進行解析,因此要讓@Autowired
起做用必須事先在 Spring 容器中聲明AutowiredAnnotationBeanPostProcessor
Bean。
清單 7. 讓 @Autowired 註釋工做起來
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- 該 BeanPostProcessor 將自動起做用,對標註 @Autowired 的 Bean 進行自動注入 --> <bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor"/> <!-- 移除 boss Bean 的屬性注入配置的信息 --> <bean id="boss" class="com.baobaotao.Boss"/> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" 紅旗 CA72"/> <property name="price" value="2000"/> </bean> </beans> |
這樣,當 Spring 容器啓動時,AutowiredAnnotationBeanPostProcessor
將掃描 Spring 容器中全部 Bean,當發現 Bean 中擁有@Autowired
註釋時就找到和其匹配(默認按類型匹配)的 Bean,並注入到對應的地方中去。
按照上面的配置,Spring 將直接採用 Java 反射機制對 Boss 中的 car
和 office
這兩個私有成員變量進行自動注入。因此對成員變量使用@Autowired
後,您大可將它們的 setter 方法(setCar()
和 setOffice()
)從 Boss 中刪除。
固然,您也能夠經過 @Autowired
對方法或構造函數進行標註,來看下面的代碼:
清單 8. 將 @Autowired 註釋標註在 Setter 方法上
package com.baobaotao; public class Boss { private Car car; private Office office; @Autowired public void setCar(Car car) { this.car = car; } @Autowired public void setOffice(Office office) { this.office = office; } … } |
這時,@Autowired
將查找被標註的方法的入參類型的 Bean,並調用方法自動注入這些 Bean。而下面的使用方法則對構造函數進行標註:
清單 9. 將 @Autowired 註釋標註在構造函數上
package com.baobaotao; public class Boss { private Car car; private Office office; @Autowired public Boss(Car car ,Office office){ this.car = car; this.office = office ; } … } |
因爲 Boss()
構造函數有兩個入參,分別是 car
和 office
,@Autowired
將分別尋找和它們類型匹配的 Bean,將它們做爲Boss(Car car ,Office office)
的入參來建立 Boss
Bean。
當候選 Bean 數目不爲 1 時的應對方法
在默認狀況下使用 @Autowired
註釋進行自動注入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個。當找不到一個匹配的 Bean 時,Spring 容器將拋出BeanCreationException
異常,並指出必須至少擁有一個匹配的 Bean。咱們能夠來作一個實驗:
清單 10. 候選 Bean 數目爲 0 時
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd "> <bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor"/> <bean id="boss" class="com.baobaotao.Boss"/> <!-- 將 office Bean 註釋掉 --> <!-- <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean>--> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" 紅旗 CA72"/> <property name="price" value="2000"/> </bean> </beans> |
因爲 office
Bean 被註釋掉了,因此 Spring 容器中將沒有類型爲 Office
的 Bean 了,而 Boss 的office
屬性標註了 @Autowired
,當啓動 Spring 容器時,異常就產生了。
當不能肯定 Spring 容器中必定擁有某個類的 Bean 時,能夠在須要自動注入該類 Bean 的地方可使用 @Autowired(required = false)
,這等於告訴 Spring:在找不到匹配 Bean 時也不報錯。來看一下具體的例子:
清單 11. 使用 @Autowired(required = false)
package com.baobaotao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Required; public class Boss { private Car car; private Office office; @Autowired public void setCar(Car car) { this.car = car; } @Autowired(required = false) public void setOffice(Office office) { this.office = office; } … } |
固然,通常狀況下,使用 @Autowired
的地方都是須要注入 Bean 的,使用了自動注入而又容許不注入的狀況通常僅會在開發期或測試期碰到(如爲了快速啓動 Spring 容器,僅引入一些模塊的 Spring 配置文件),因此@Autowired(required = false)
會不多用到。
和找不到一個類型匹配 Bean 相反的一個錯誤是:若是 Spring 容器中擁有多個候選 Bean,Spring 容器在啓動時也會拋出 BeanCreationException
異常。來看下面的例子:
清單 12. 在 beans.xml 中配置兩個 Office 類型的 Bean
… <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> <bean id="office2" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> … |
咱們在 Spring 容器中配置了兩個類型爲 Office
類型的 Bean,當對 Boss 的 office
成員變量進行自動注入時,Spring 容器將沒法肯定到底要用哪個 Bean,所以異常發生了。
Spring 容許咱們經過 @Qualifier
註釋指定注入 Bean 的名稱,這樣歧義就消除了,能夠經過下面的方法解決異常:
清單 13. 使用 @Qualifier 註釋指定注入 Bean 的名稱
@Autowired public void setOffice(@Qualifier("office")Office office) { this.office = office; } |
@Qualifier("office")
中的 office
是 Bean 的名稱,因此 @Autowired
和@Qualifier
結合使用時,自動注入的策略就從 byType 轉變成 byName 了。@Autowired
能夠對成員變量、方法以及構造函數進行註釋,而@Qualifier
的標註對象是成員變量、方法入參、構造函數入參。正是因爲註釋對象的不一樣,因此 Spring 不將 @Autowired
和@Qualifier
統一成一個註釋類。下面是對成員變量和構造函數入參進行註釋的代碼:
對成員變量進行註釋:
清單 14. 對成員變量使用 @Qualifier 註釋
public class Boss { @Autowired private Car car; @Autowired @Qualifier("office") private Office office; … } |
對構造函數入參進行註釋:
清單 15. 對構造函數變量使用 @Qualifier 註釋
public class Boss { private Car car; private Office office; @Autowired public Boss(Car car , @Qualifier("office")Office office){ this.car = car; this.office = office ; } } |
@Qualifier
只能和 @Autowired
結合使用,是對 @Autowired
有益的補充。通常來說,@Qualifier
對方法簽名中入參進行註釋會下降代碼的可讀性,而對成員變量註釋則相對好一些。
使用 JSR-250 的註釋
Spring 不但支持本身定義的 @Autowired
的註釋,還支持幾個由 JSR-250 規範定義的註釋,它們分別是 @Resource
、@PostConstruct
以及 @PreDestroy
。
@Resource
@Resource
的做用至關於 @Autowired
,只不過 @Autowired
按 byType 自動注入,面@Resource
默認按 byName 自動注入罷了。@Resource
有兩個屬性是比較重要的,分別是 name 和 type,Spring 將@Resource
註釋的 name 屬性解析爲 Bean 的名字,而 type 屬性則解析爲 Bean 的類型。因此若是使用 name 屬性,則使用 byName 的自動注入策略,而使用 type 屬性時則使用 byType 自動注入策略。若是既不指定 name 也不指定 type 屬性,這時將經過反射機制使用 byName 自動注入策略。
Resource 註釋類位於 Spring 發佈包的 lib/j2ee/common-annotations.jar 類包中,所以在使用以前必須將其加入到項目的類庫中。來看一個使用@Resource
的例子:
清單 16. 使用 @Resource 註釋的 Boss.java
package com.baobaotao; import javax.annotation.Resource; public class Boss { // 自動注入類型爲 Car 的 Bean @Resource private Car car; // 自動注入 bean 名稱爲 office 的 Bean @Resource(name = "office") private Office office; } |
通常狀況下,咱們無需使用相似於 @Resource(type=Car.class)
的註釋方式,由於 Bean 的類型信息能夠經過 Java 反射從代碼中獲取。
要讓 JSR-250 的註釋生效,除了在 Bean 類中標註這些註釋外,還須要在 Spring 容器中註冊一個負責處理這些註釋的 BeanPostProcessor
:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/> |
CommonAnnotationBeanPostProcessor
實現了 BeanPostProcessor
接口,它負責掃描使用了 JSR-250 註釋的 Bean,並對它們進行相應的操做。
@PostConstruct 和 @PreDestroy
Spring 容器中的 Bean 是有生命週期的,Spring 容許在 Bean 在初始化完成後以及 Bean 銷燬前執行特定的操做,您既能夠經過實現 InitializingBean/DisposableBean 接口來定製初始化以後 / 銷燬以前的操做方法,也能夠經過 <bean> 元素的 init-method/destroy-method 屬性指定初始化以後 / 銷燬以前調用的操做方法。關於 Spring 的生命週期,筆者在《精通 Spring 2.x—企業應用開發精解》第 3 章進行了詳細的描述,有興趣的讀者能夠查閱。
JSR-250 爲初始化以後/銷燬以前方法的指定定義了兩個註釋類,分別是 @PostConstruct 和 @PreDestroy,這兩個註釋只能應用於方法上。標註了 @PostConstruct 註釋的方法將在類實例化後調用,而標註了 @PreDestroy 的方法將在類銷燬以前調用。
清單 17. 使用 @PostConstruct 和 @PreDestroy 註釋的 Boss.java
package com.baobaotao; import javax.annotation.Resource; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class Boss { @Resource private Car car; @Resource(name = "office") private Office office; @PostConstruct public void postConstruct1(){ System.out.println("postConstruct1"); } @PreDestroy public void preDestroy1(){ System.out.println("preDestroy1"); } … } |
您只須要在方法前標註 @PostConstruct
或 @PreDestroy
,這些方法就會在 Bean 初始化後或銷燬以前被 Spring 容器執行了。
咱們知道,不論是經過實現 InitializingBean
/DisposableBean
接口,仍是經過 <bean> 元素的init-method/destroy-method
屬性進行配置,都只能爲 Bean 指定一個初始化 / 銷燬的方法。可是使用 @PostConstruct
和 @PreDestroy
註釋卻能夠指定多個初始化 / 銷燬方法,那些被標註 @PostConstruct
或 @PreDestroy
註釋的方法都會在初始化 / 銷燬時被執行。
經過如下的測試代碼,您將能夠看到 Bean 的初始化 / 銷燬方法是如何被執行的:
清單 18. 測試類代碼
package com.baobaotao; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AnnoIoCTest { public static void main(String[] args) { String[] locations = {"beans.xml"}; ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(locations); Boss boss = (Boss) ctx.getBean("boss"); System.out.println(boss); ctx.destroy();// 關閉 Spring 容器,以觸發 Bean 銷燬方法的執行 } } |
這時,您將看到標註了 @PostConstruct
的 postConstruct1()
方法將在 Spring 容器啓動時,建立Boss
Bean 的時候被觸發執行,而標註了 @PreDestroy
註釋的 preDestroy1()
方法將在 Spring 容器關閉前銷燬Boss
Bean 的時候被觸發執行。
使用 <context:annotation-config/> 簡化配置
Spring 2.1 添加了一個新的 context 的 Schema 命名空間,該命名空間對註釋驅動、屬性文件引入、加載期織入等功能提供了便捷的配置。咱們知道註釋自己是不會作任何事情的,它僅提供元數據信息。要使元數據信息真正起做用,必須讓負責處理這些元數據的處理器工做起來。
而咱們前面所介紹的 AutowiredAnnotationBeanPostProcessor
和 CommonAnnotationBeanPostProcessor
就是處理這些註釋元數據的處理器。可是直接在 Spring 配置文件中定義這些 Bean 顯得比較笨拙。Spring 爲咱們提供了一種方便的註冊這些BeanPostProcessor
的方式,這就是 <context:annotation-config/>。請看下面的配置:
清單 19. 調整 beans.xml 配置文件
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/> <bean id="boss" class="com.baobaotao.Boss"/> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" 紅旗 CA72"/> <property name="price" value="2000"/> </bean> </beans> |
<context:annotationconfig/> 將隱式地向 Spring 容器註冊 AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
、PersistenceAnnotationBeanPostProcessor
以及equiredAnnotationBeanPostProcessor
這 4 個 BeanPostProcessor。
在配置文件中使用 context 命名空間以前,必須在 <beans> 元素中聲明 context 命名空間。
使用 @Component
雖然咱們能夠經過 @Autowired
或 @Resource
在 Bean 類中使用自動注入功能,可是 Bean 仍是在 XML 文件中經過 <bean> 進行定義 —— 也就是說,在 XML 配置文件中定義 Bean,經過@Autowired
或 @Resource
爲 Bean 的成員變量、方法入參或構造函數入參提供自動注入的功能。可否也經過註釋定義 Bean,從 XML 配置文件中徹底移除 Bean 定義的配置呢?答案是確定的,咱們經過 Spring 2.5 提供的@Component
註釋就能夠達到這個目標了。
爲何 @Repository 只能標註在 DAO 類上呢?這是由於該註解的做用不僅是將類識別爲 Bean,同時它還能將所標註的類中拋出的數據訪問異常封裝爲 Spring 的數據訪問異常類型。 Spring 自己提供了一個豐富的而且是與具體的數據訪問技術無關的數據訪問異常結構,用於封裝不一樣的持久層框架拋出的異常,使得異常獨立於底層的框架。
Spring 2.5 在 @Repository 的基礎上增長了功能相似的額外三個註解:@Component、@Service、@Constroller,它們分別用於軟件系統的不一樣層次:
經過在類上使用 @Repository、@Component、@Service 和 @Constroller 註解,Spring 會自動建立相應的 BeanDefinition 對象,並註冊到 ApplicationContext 中。這些類就成了 Spring 受管組件。這三個註解除了做用於不一樣軟件層次的類,其使用方式與 @Repository 是徹底相同的。
下面,咱們徹底使用註釋定義 Bean 並完成 Bean 之間裝配:
清單 20. 使用 @Component 註釋的 Car.java
package com.baobaotao; import org.springframework.stereotype.Component; @Component public class Car { … } |
僅須要在類定義處,使用 @Component
註釋就能夠將一個類定義了 Spring 容器中的 Bean。下面的代碼將 Office
定義爲一個 Bean:
清單 21. 使用 @Component 註釋的 Office.java
package com.baobaotao; import org.springframework.stereotype.Component; @Component public class Office { private String officeNo = "001"; … } |
這樣,咱們就能夠在 Boss 類中經過 @Autowired
注入前面定義的 Car
和 Office Bean
了。
清單 22. 使用 @Component 註釋的 Boss.java
package com.baobaotao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component("boss") public class Boss { @Autowired private Car car; @Autowired private Office office; … } |
@Component
有一個可選的入參,用於指定 Bean 的名稱,在 Boss 中,咱們就將 Bean 名稱定義爲「boss
」。通常狀況下,Bean 都是 singleton 的,須要注入 Bean 的地方僅須要經過 byType 策略就能夠自動注入了,因此大可沒必要指定 Bean 的名稱。
在使用 @Component
註釋後,Spring 容器必須啓用類掃描機制以啓用註釋驅動 Bean 定義和註釋驅動 Bean 自動注入的策略。Spring 2.5 對 context 命名空間進行了擴展,提供了這一功能,請看下面的配置:
清單 23. 簡化版的 beans.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.baobaotao"/> </beans> |
這裏,全部經過 <bean> 元素定義 Bean 的配置內容已經被移除,僅須要添加一行 <context:component-scan/> 配置就解決全部問題了——Spring XML 配置文件獲得了極致的簡化(固然配置元數據仍是須要的,只不過以註釋形式存在罷了)。<context:component-scan/> 的 base-package 屬性指定了須要掃描的類包,類包及其遞歸子包中全部的類都會被處理。
<context:component-scan/> 還容許定義過濾器將基包下的某些類歸入或排除。Spring 支持如下 4 種類型的過濾方式,經過下表說明:
表 1. 掃描過濾方式
過濾器類型 | 說明 |
---|---|
註釋 | 假如 com.baobaotao.SomeAnnotation 是一個註釋類,咱們能夠將使用該註釋的類過濾出來。 |
類名指定 | 經過全限定類名進行過濾,如您能夠指定將 com.baobaotao.Boss 歸入掃描,而將 com.baobaotao.Car 排除在外。 |
正則表達式 | 經過正則表達式定義過濾的類,以下所示: com\.baobaotao\.Default.* |
AspectJ 表達式 | 經過 AspectJ 表達式定義過濾的類,以下所示: com. baobaotao..*Service+ |
下面是一個簡單的例子:
<context:component-scan base-package="com.baobaotao"> <context:include-filter type="regex" expression="com\.baobaotao\.service\..*"/> <context:exclude-filter type="aspectj" expression="com.baobaotao.util..*"/> </context:component-scan> |
值得注意的是 <context:component-scan/> 配置項不但啓用了對類包進行掃描以實施註釋驅動 Bean 定義的功能,同時還啓用了註釋驅動自動注入的功能(即還隱式地在內部註冊了AutowiredAnnotationBeanPostProcessor
和 CommonAnnotationBeanPostProcessor
),所以當使用 <context:component-scan/> 後,就能夠將 <context:annotation-config/> 移除了。
默認狀況下經過 @Component
定義的 Bean 都是 singleton 的,若是須要使用其它做用範圍的 Bean,能夠經過@Scope
註釋來達到目標,如如下代碼所示:
@scopee
清單 24. 經過 @Scope 指定 Bean 的做用範圍
package com.baobaotao; import org.springframework.context.annotation.Scope; … @Scope("prototype") @Component("boss") public class Boss { … } |
這樣,當從 Spring 容器中獲取 boss
Bean 時,每次返回的都是新的實例了。
採用具備特殊語義的註釋
Spring 2.5 中除了提供 @Component
註釋外,還定義了幾個擁有特殊語義的註釋,它們分別是:@Repository
、@Service
和@Controller
。在目前的 Spring 版本中,這 3 個註釋和 @Component
是等效的,可是從註釋類的命名上,很容易看出這 3 個註釋分別和持久層、業務層和控制層(Web 層)相對應。雖然目前這 3 個註釋和@Component
相比沒有什麼新意,但 Spring 將在之後的版本中爲它們添加特殊的功能。因此,若是 Web 應用程序採用了經典的三層分層結構的話,最好在持久層、業務層和控制層分別採用@Repository
、@Service
和 @Controller
對分層中的類進行註釋,而用@Component
對那些比較中立的類進行註釋。
註釋配置和 XML 配置的適用場合
是否有了這些 IOC 註釋,咱們就能夠徹底摒除原來 XML 配置的方式呢?答案是否認的。有如下幾點緣由:
JdbcTemplate
、SessionFactoryBean
等),註釋配置將沒法實施,此時 XML 配置是惟一可用的方式。@Transaction
事務註釋,使用 aop/tx 命名空間的事務配置更加靈活和簡單。因此在實現應用中,咱們每每須要同時使用註釋配置和 XML 配置,對於類級別且不會發生變更的配置能夠優先考慮註釋配置;而對於那些第三方類以及容易發生調整的配置則應優先考慮使用 XML 配置。Spring 會在具體實施 Bean 建立和 Bean 注入以前將這兩種配置方式的元信息融合在一塊兒。