天天看點

[email protected]注解與自動裝配

1   配置檔案的方法

我們編寫spring 架構的代碼時候。一直遵循是這樣一個規則:所有在spring中注入的bean 都建議定義成私有的域變量。并且要配套寫上 get 和 set方法。

Boss 擁有 Office 和 Car 類型的兩個屬性:   

清單 3. Boss.java

[java]  view plain copy print ?

  1. package com.baobaotao;     
  2. public class Boss {     
  3.     private Car car;     
  4.     private Office office;     
  5.     // 省略 get/setter     
  6.     @Override    
  7.     public String toString() {     
  8.         return "car:" + car + "/n" + "office:" + office;     
  9.     }     
  10. }     

  System.out.println必須實作toString方法

我們在 Spring 容器中将 Office 和 Car 聲明為 Bean,并注入到 Boss Bean 中:下面是使用傳統 XML 完成這個工作的配置檔案 beans.xml:   

清單 4. beans.xml 将以上三個類配置成 Bean   

[xhtml]  view plain copy print ?

  1. <?xml version="1.0" encoding="UTF-8" ?>     
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans      
  5. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">     
  6.     <bean id="boss" class="com.baobaotao.Boss">     
  7.         <property name="car" ref="car"/>     
  8.         <property name="office" ref="office" />     
  9.     </bean>     
  10.     <bean id="office" class="com.baobaotao.Office">     
  11.         <property name="officeNo" value="002"/>     
  12.     </bean>     
  13.     <bean id="car" class="com.baobaotao.Car" scope="singleton">     
  14.         <property name="brand" value=" 紅旗 CA72"/>     
  15.         <property name="price" value="2000"/>     
  16.     </bean>     
  17. </beans>     

當我們運作以下代碼時,控制台将正确打出 boss 的資訊:   

清單 5. 測試類:AnnoIoCTest.java   

[java]  view plain copy print ?

  1. import org.springframework.context.ApplicationContext;     
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;     
  3. public class AnnoIoCTest {     
  4.     public static void main(String[] args) {     
  5.         String[] locations = {"beans.xml"};     
  6.         ApplicationContext ctx =      
  7.             new ClassPathXmlApplicationContext(locations);     
  8.         Boss boss = (Boss) ctx.getBean("boss");     
  9.         System.out.println(boss);     
  10.     }     
  11. }     
這說明 Spring 容器已經正确完成了 Bean 建立和裝配的工作。   

2   @Autowired 

Spring 2.5 引入了 @Autowired 注釋,它可以對類成員變量、方法及構造函數進行标注,完成自動裝配的工作。 通過 @Autowired的使用來消除 set ,get方法。

要實作我們要精簡程式的目的。需要這樣來處理: 

* 在applicationContext.xml中加入: 

[c-sharp]  view plain copy print ?

  1. <!-- 該 BeanPostProcessor 将自動對标注 @Autowired 的 Bean 進行注入 -->     
  2.   <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>  

Spring 通過一個 BeanPostProcessor 對 @Autowired 進行解析,是以要讓 @Autowired 起作用必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean。   

* 修改在原來注入spirng容器中的bean的方法。 

     在域變量上加上标簽@Autowired,并且去掉 相應的get 和set方法

清單 6. 使用 @Autowired 注釋的 Boss.java   

[java]  view plain copy print ?

  1. package com.baobaotao;     
  2. import org.springframework.beans.factory.annotation.Autowired;     
  3. public class Boss {     
  4.     @Autowired    
  5.     private Car car;     
  6.     @Autowired    
  7.     private Office office;     
  8.     …     
  9. }     

* 在applicatonContext.xml中 把原來 引用的<porpery >标簽也去掉。

[xhtml]  view plain copy print ?

  1. <?xml version="1.0" encoding="UTF-8" ?>     
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans      
  5. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">     
  6.     <!-- 該 BeanPostProcessor 将自動起作用,對标注 @Autowired 的 Bean 進行自動注入 -->     
  7.     <bean class="org.springframework.beans.factory.annotation.     
  8.         AutowiredAnnotationBeanPostProcessor"/>     
  9.     <!-- 移除 boss Bean 的屬性注入配置的資訊 -->     
  10.     <bean id="boss" class="com.baobaotao.Boss"/>     
  11.     <bean id="office" class="com.baobaotao.Office">     
  12.         <property name="officeNo" value="001"/>     
  13.     </bean>     
  14.     <bean id="car" class="com.baobaotao.Car" scope="singleton">     
  15.         <property name="brand" value=" 紅旗 CA72"/>     
  16.         <property name="price" value="2000"/>     
  17.     </bean>     
  18. </beans>    

 這樣,當 Spring 容器啟動時,AutowiredAnnotationBeanPostProcessor 将掃描 Spring 容器中所有 Bean,當發現 Bean 中擁有 @Autowired 注釋時就找到和其比對(預設按類型比對)的 Bean,并注入到對應的地方中去。   

按照上面的配置,Spring 将直接采用 Java 反射機制對 Boss 中的 car 和 office 這兩個私有成員變量進行自動注入。是以對成員變量使用 @Autowired 後,您大可将它們的 setter 方法(setCar() 和 setOffice())從 Boss 中删除。   

當然,您也可以通過 @Autowired 對方法或構造函數進行标注,如果構造函數有兩個入參,分别是 bean1 和 bean2,@Autowired 将分别尋找和它們類型比對的 Bean,将它們作為 CountryService (Bean1 bean1 ,Bean2 bean2) 的入參來建立 CountryService Bean。來看下面的代碼:  對方法

[java]  view plain copy print ?

  1. package com.baobaotao;     
  2. public class Boss {     
  3.     private Car car;     
  4.     private Office office;     
  5.      @Autowired    
  6.     public void setCar(Car car) {     
  7.         this.car = car;     
  8.     }     
  9.     @Autowired    
  10.     public void setOffice(Office office) {     
  11.         this.office = office;     
  12.     }     
  13.     …     
  14. }     

這時,@Autowired 将查找被标注的方法的入參類型的 Bean,并調用方法自動注入這些 Bean。而下面的使用方法則對構造函數進行标注:   

[java]  view plain copy print ?

  1. package com.baobaotao;     
  2. public class Boss {     
  3.     private Car car;     
  4.     private Office office;     
  5.     @Autowired    
  6.     public Boss(Car car ,Office office){     
  7.         this.car = car;     
  8.         this.office = office ;     
  9.     }     
  10.     …     
  11. }     

由于 Boss() 構造函數有兩個入參,分别是 car 和 office,@Autowired 将分别尋找和它們類型比對的 Bean,将它們作為 Boss(Car car ,Office office) 的入參來建立 Boss Bean。