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()方法。程序代碼如下。
同樣創建一個教師類 Teacher,定義姓名、性別和年齡等屬性,並添加對應的 set()與 get()方法。程序代碼如下。
創建教學檔案類 TeachFile,定義 Teacher 和 Student 兩個屬性,並添加 print()方法。用於輸出教師與學生的信息。程序代碼如下。
在配置文件applicationContext.xml中定義剛剛創建的類,併爲其賦值。其中 TeachFile 類採用了自動裝配。程序代碼如下。
在這個配置文件中定義了 Student 類和 Teacher 類,併爲姓名、年齡和性別屬性賦值。在定義 TeachFile 類時,沒有傳遞任何參數,而是採用了 autowire 屬性自動配置 TeachFile類所需要的屬性。下面編寫一個主類 PrintInfo 類來輸出檔案信息。程序代碼如下。
輸出結果:
四月 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 類注入到對應的屬性中。語法格式如下。
在 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 使用手動裝配注入依賴屬性