當我們要往一個bean的某個屬性里注入另外一個bean,我們會使用<property> + <ref/>標簽的形式。但是對於大型項目,假設有一個bean A被多個bean引用注入,如果A的id因為某種原因修改了,那么所有引用了A的bean的<ref/>標簽內容都得修改,這時候如果使用autowire="byType",那么引用了A的bean就完全不用修改了。autowire到底都什么用?我們繼續往下看。
autowire的用法:
<bean id="auto" class="example.autoBean" autowire="byType"/>
autowire屬性有5種模式,如下表:
| 模式 |
說明 |
| no |
(默認)不采用autowire機制.。這種情況,當我們需要使用依賴注入,只能用<ref/>標簽。 |
| byName |
通過屬性的名稱自動裝配(注入)。Spring會在容器中查找名稱與bean屬性名稱一致的bean,並自動注入到bean屬性中。當然bean的屬性需要有setter方法。例如:bean A有個屬性master,master的setter方法就是setMaster,A設置了autowire="byName",那么Spring就會在容器中查找名為master的bean通過setMaster方法注入到A中。 |
| byType |
通過類型自動裝配(注入)。Spring會在容器中查找類(Class)與bean屬性類一致的bean,並自動注入到bean屬性中,如果容器中包含多個這個類型的bean,Spring將拋出異常。如果沒有找到這個類型的bean,那么注入動作將不會執行。 |
| constructor |
類似於byType,但是是通過構造函數的參數類型來匹配。假設bean A有構造函數A(B b, C c),那么Spring會在容器中查找類型為B和C的bean通過構造函數A(B b, C c)注入到A中。與byType一樣,如果存在多個bean類型為B或者C,則會拋出異常。但時與byType不同的是,如果在容器中找不到匹配的類的bean,將拋出異常,因為Spring無法調用構造函數實例化這個bean。 |
| default |
采用父級標簽(即beans的default-autowire屬性)的配置。 |
其中byType和constructor模式也支持數組和強類型集合(即指定了集合元素類型)。如bean A有個屬性定義是List<Foo>類型,Spring會在容器中查找所有類型為Foo的bean,注入到該屬性。記住是Foo,不是List。
另外如果集合和Map集合,那么Map的key必須是String類型,Spring會根據value的類型去匹配。例如有屬性bean A中有一個屬性為Map<String, Foo> p,容器中有bean B和C類型均為Foo,那么A實例化完成后,p屬性的值為:{"B":B的實例對象,"C":C的實例對象}。
除了可以給單獨一個bean配置autowire屬性,我們還可以給某個bean配置文件的<beans/>標簽添加default-autowire屬性。在<beans/>標簽中指定default-autowire屬性,那么對於子標簽<bean/>如果沒有單獨的設置autowire屬性,那么將采用父標簽<beans/>的default-autowire屬性的模式,如果單獨設置了autowire屬性,則采用自己的模式。
雖然autowrie給我們帶來配置的便利性,但是也有缺點,比如會導致bean的關系沒那么顯而易見,所以用autowire還是ref還是需要根據項目來決定。
autowire-candidate
前面我們說到配置有autowire屬性的bean,Spring在實例化這個bean的時候會在容器中查找匹配的bean對autowire bean進行屬性注入,這些被查找的bean我們稱為候選bean。作為候選bean,我憑什么就要被你用,老子不給你用。所以候選bean給自己增加了autowire-candidate="false"屬性(默認是true),那么容器就不會把這個bean當做候選bean了,即這個bean不會被當做自動裝配對象。同樣,<beans/>標簽可以定義default-autowire-candidate="false"屬性讓它包含的所有bean都不做為候選bean。我的地盤我做主。
