Spring之自動裝配解析

set注入和構造注入有時在做配置時比較麻煩。所以框架爲了提高開發效率,提供自動裝配功能,簡化配置。Spring框架式默認不支持自動裝配的,要想使用自動裝配需要修改spring配置文件中<bean>標籤的autowire屬性。自動裝配屬性有5個值可選,分別代表不同的含義。 

1、byName

 從Spring環境中獲取目標對象時,目標對象中的屬性會根據名稱在整個Spring環境中查找<bean>標籤的id屬性值。如果有相同的,那麼獲取這個對象,實現關聯。

 整個Spring環境:表示所有的spring配置文件中查找,那麼id不能有重複的。

 

2、byType

 從Spring環境中獲取目標對象時,目標對象中的屬性會根據類型在整個spring環境中查找<bean>標籤的class屬性值。如果有相同的,那麼獲取這個對象,實現關聯。

        缺點:如果存在多個相同類型的bean對象,會出錯。

如果屬性爲單一類型的數據,那麼查找到多個關聯對象會發生錯誤。

如果屬性爲數組或集合(泛型)類型,那麼查找到多個關聯對象不會發生異常。

3、constructor(3.x以上已不能用)

 使用構造方法完成對象注入,其實也是根據構造方法的參數類型進行對象查找,相當於採用byType的方式。如果沒找到則拋出異常

4、autodetect

 自動選擇:如果對象沒有無參數的構造方法,那麼自動選擇constructor的自動裝配方式進行構造注入。如果對象含有無參數的構造方法,那麼自動選擇byType的自動裝配方式進行setter注入。                      

5、no

默認情況下,不自動裝配,通過“ref”attribute手動設定。 

        <bean>標籤的 autowire 屬性,它負責自動裝配<bean>標籤定義 JavaBean 的屬性。這樣做可以省去很多配置 JavaBean 屬性的標籤代碼,使代碼整潔、美觀。但是它也有負面影響,即使用自動裝配之後,無法從配置文件中讀懂 JavaBean 需要什麼屬性。自動裝配存在很多不正確的裝配問題,例如錯誤裝載屬性、“byType”屬性和“constructor”屬性對相同類型參數無法判斷等。當然,將自動裝配和手動裝配混合使用也能解決此問題。下面通過一個實例來分析如何使用自動裝配。

首先創建創建一個學生類 Student,定義學號、姓名、性別、年齡等屬性,並添加對

應的 set()與 get()方法。程序代碼如下。

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. package com.autobean;  
  2.   
  3. public class Student {  
  4.     private String ID;  
  5.     private String name;  
  6.     private int age;  
  7.     private String sex;  
  8.   
  9.     public String getID() {  
  10.         return ID;  
  11.     }  
  12.   
  13.     public void setID(String iD) {  
  14.         ID = iD;  
  15.     }  
  16.   
  17.     public String getName() {  
  18.         return name;  
  19.     }  
  20.   
  21.     public void setName(String name) {  
  22.         this.name = name;  
  23.     }  
  24.   
  25.     public int getAge() {  
  26.         return age;  
  27.     }  
  28.   
  29.     public void setAge(int age) {  
  30.         this.age = age;  
  31.     }  
  32.   
  33.     public String getSex() {  
  34.         return sex;  
  35.     }  
  36.   
  37.     public void setSex(String sex) {  
  38.         this.sex = sex;  
  39.     }  
  40.   
  41. }  
同樣創建一個教師類 Teacher,定義姓名、性別和年齡等屬性,並添加對應的 set()與 get()方法。程序代碼如下。
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. package com.autobean;  
  2.   
  3. public class Teacher {  
  4.     private String name;  
  5.     private int age;  
  6.     private String sex;  
  7.   
  8.     public String getName() {  
  9.         return name;  
  10.     }  
  11.   
  12.     public void setName(String name) {  
  13.         this.name = name;  
  14.     }  
  15.   
  16.     public int getAge() {  
  17.         return age;  
  18.     }  
  19.   
  20.     public void setAge(int age) {  
  21.         this.age = age;  
  22.     }  
  23.   
  24.     public String getSex() {  
  25.         return sex;  
  26.     }  
  27.   
  28.     public void setSex(String sex) {  
  29.         this.sex = sex;  
  30.     }  
  31.   
  32. }  

創建教學檔案類 TeachFile,定義 Teacher 和 Student 兩個屬性,並添加 print()方法。用於輸出教師與學生的信息。程序代碼如下。 

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. package com.autobean;  
  2.   
  3. public class TeachFile {  
  4.     private Teacher teacher;  
  5.     private Student student;  
  6.     public TeachFile() {  
  7.     }  
  8.     public TeachFile(Teacher teacher, Student student) {  
  9.         this.teacher = teacher;  
  10.         this.student = student;  
  11.     }  
  12.   
  13.     public Student getStudent() {  
  14.         return this.student;  
  15.     }  
  16.   
  17.     public void setStudent(Student student1) {  
  18.         this.student = student1;  
  19.     }  
  20.   
  21.     public Teacher getTeacher() {  
  22.         return teacher;  
  23.     }  
  24.   
  25.     public void setTeacher(Teacher teacher) {  
  26.         this.teacher = teacher;  
  27.     }  
  28.   
  29.     public void print() {  
  30.         System.out.println("------教師信息------");  
  31.         System.out.println("姓名:" + teacher.getName());  
  32.         System.out.println("年齡:" + teacher.getAge());  
  33.         System.out.println("性別:" + teacher.getSex());  
  34.         System.out.println();  
  35.         System.out.println("------學生信息------");  
  36.         System.out.println("學號:" + student.getID());  
  37.         System.out.println("姓名:" + student.getName());  
  38.         System.out.println("年齡:" + student.getAge());  
  39.         System.out.println("性別:" + student.getSex());  
  40.     }  
  41.   
  42. }  

在配置文件applicationContext.xml中定義剛剛創建的類,併爲其賦值。其中 TeachFile 類採用了自動裝配。程序代碼如下。 

[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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" xmlns:p="http://www.springframework.org/schema/p"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">  
  5.   
  6.     <bean id="student" class="com.autobean.Student">  
  7.         <property name="ID" value="80" />   
  8.         <property name="name" value="阿王" />   
  9.         <property name="age" value="23" />   
  10.         <property name="sex" value="男" />   
  11.     </bean>  
  12.     <bean id="teacher" class="com.autobean.Teacher">  
  13.         <property name="name" value="何老師" />   
  14.         <property name="age" value="43" />   
  15.         <property name="sex" value="女" />   
  16.     </bean>  
  17.     <!-- 默認情況下,通過'ref’來裝配bean -->  
  18.     <bean id="teachFile1" class="com.autobean.TeachFile" >  
  19.      <property name="teacher" ref="teacher" />  
  20.      <property name="student" ref="student" />  
  21.     </bean>  
  22.     <!--根據byName自動裝配bean -->  
  23.     <bean id="teachFile2" autowire="byName"  class="com.autobean.TeachFile" />  
  24.       <!--根據byType自動裝配bean -->  
  25.     <bean id="teachFile3" autowire="byType" class="com.autobean.TeachFile" />  
  26.       <!--根據constructor自動裝配bean -->  
  27.     <bean id="teachFile4" autowire="constructor" class="com.autobean.TeachFile"/>  
  28. </beans>  

在這個配置文件中定義了 Student 類和 Teacher 類,併爲姓名、年齡和性別屬性賦值。在定義 TeachFile 類時,沒有傳遞任何參數,而是採用了 autowire 屬性自動配置 TeachFile類所需要的屬性。下面編寫一個主類 PrintInfo 類來輸出檔案信息。程序代碼如下。

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. package com.autobean;  
  2.   
  3. import org.springframework.beans.factory.BeanFactory;  
  4. import org.springframework.beans.factory.xml.XmlBeanFactory;  
  5. import org.springframework.core.io.ClassPathResource;  
  6. import org.springframework.core.io.Resource;  
  7.   
  8. public class PrintInfo {  
  9.   
  10.     public static void main(String[] args) {  
  11.         Resource res = new ClassPathResource("applicationContext.xml");  
  12.         BeanFactory bf = new XmlBeanFactory(res);  
  13.         TeachFile tf1 = (TeachFile) bf.getBean("teachFile1");  
  14.         TeachFile tf2 = (TeachFile) bf.getBean("teachFile2");  
  15.         TeachFile tf3 = (TeachFile) bf.getBean("teachFile3");  
  16.         TeachFile tf4 = (TeachFile) bf.getBean("teachFile4");  
  17.   
  18.       
  19.         System.out.println("默認情況下,通過'ref’來裝配bean");  
  20.         tf1.print();  
  21.         System.out.println("根據byName自動裝配bean");  
  22.         tf2.print();  
  23.         System.out.println("根據byType自動裝配bean");  
  24.         tf3.print();  
  25.         System.out.println("根據constructor自動裝配bean");  
  26.         tf4.print();  
  27.       
  28.     }  
  29.   
  30. }  

輸出結果:

四月 02, 2015 8:16:48 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
默認情況下,通過'ref’來裝配bean
------教師信息------
姓名:何老師
年齡:43
性別:女

------學生信息------
學號:80
姓名:阿王
年齡:23
性別:男
根據byName自動裝配bean
------教師信息------
姓名:何老師
年齡:43
性別:女

------學生信息------
學號:80
姓名:阿王
年齡:23
性別:男
根據byType自動裝配bean
------教師信息------
姓名:何老師
年齡:43
性別:女

------學生信息------
學號:80
姓名:阿王
年齡:23
性別:男
根據constructor自動裝配bean
------教師信息------
姓名:何老師
年齡:43
性別:女

------學生信息------
學號:80
姓名:阿王
年齡:23
性別:男


在上面實例的配置文件 appContext.xml 中,TeachFile 類採用4種裝配,將 Teacher
類和 Student 類注入到對應的屬性中。語法格式如下。

[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. <bean autowire="byName" id="teachFile" class="TeachFile" />  
在 autowire 屬性中指定類型爲“byName”。autowire 屬性共支持 5 種裝配類型,下面
分別介紹每種裝配類型的用法。
(1)no:autowire 採用的默認值,採用自動裝配。必須使用 ref 直接引用其他 Bean,這樣可以增加代碼的可讀性,並且不易出錯。
(2)byName:以屬性名區分自動裝配。在容器中尋找與 JavaBean 的屬性名相同的JavaBean,並將其自動裝配到 JavaBean 中。如果用上面的實例來解釋,TeachFile 類的實例對象 teachFile 包含的兩個屬性分別是 Teacher 類和 Student 類的實例對象,而配置文件中已經定義了這兩個類的實例。在定義 teachFile 實例時指定了自動裝配類型爲“byName”,容器會自動尋找 teachFile 實例需要的屬性(即 teacher 和 student 兩個 JavaBean),並注入到 teachFile 實例中。此類自動裝配類型存在錯誤裝配 JavaBean 的可能,如果配置文件中定義了與需要自動裝配的 JavaBean 屬性相同而類型不同的 JavaBean,那麼它會錯誤地注入不同類型的JavaBean。讀者可以將上面實例中的配置文件修改一下,將 student 和 teacher 兩個JavaBean 的類型保持不變,將名字調換一下,便會出現此問題。這時自動裝配無法解決此問題,只能通過混合使用手動裝配來指定裝配哪個 JavaBean。
(3)byType:以屬性類型區分自動裝配。容器會自動尋找與 JavaBean 的屬性類型相同的 JavaBean 的定義,並將其注入到需要自動裝配的 JavaBean 中。如果將上面配置JavaBean 自動裝配的類型修改爲 byType,也可以實現相同的結果。這種自動裝配類型也會出現無法自動裝配的情況。例如在配置文件中再次添加一個Student 類或 Teacher 類的實現對象,byType 自動裝配類型會因爲無法自動識別裝配哪一個 JavaBean 而拋出org.springframework.beans.factory.UnsatisfiedDependencyException 異常。要解決此
問題,只能通過混合使用手動裝配來指定裝配哪個 JavaBean。
(4)constructor:通過構造方法的參數類型自動裝配。此類型會使容器自動尋找與JavaBean 的構造方法的參數類型相同的 Bean,並注入到需要自動裝配的 JavaBean 中。它
與 byType 類型存在相同的無法識別自動裝配的情況。
(5)autudetect:這是最後一個自動裝配類型,它首先使用 constructor 方式自動裝配,然後使用 byType 方式。當然它也存在與 byType 和 constructor 相同的異常情況。建
議在使用自動裝配時,把容易出現問題的 JavaBean 使用手動裝配注入依賴屬性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章