詳解依賴注入與自動裝配

在我面試的時候,常會問面試者一個問題,就是依賴注入有幾種方式,發現面試者的回答五花八門,有回答兩種的,也有回答三種的,四種的。其實正確的答案是兩種:構造器注入和setter注入。
提到依賴注入,就不能不說裝配。有些初學者總是會把這兩個概念搞混,這個博文就是來跟大家討論這兩個概念以及其中詳細的原理。
依賴注入的本質就是裝配,裝配是依賴注入的具體行爲。這就是兩者的關係。例如:
這是使用構造器注入來裝配bean。
這是使用setter注入,p是spring的名稱空間,可以用來代替標籤。
以上就是兩種依賴注入方式。上面的注入只是基本類型的注入。下面介紹一下常用的注入配置:
1.構造器注入對象屬性


2. 屬性注入對象屬性

3. 屬性爲List類型或數組類型屬性注入








list元素的成員也可以是,,,其中是用來裝配匿名bean的,是用來裝配null值的。匿名bean會在下面介紹。
4.屬性爲set類型的屬性注入
set類型與list類型注入是一樣的,只是標籤改成就可以了。並且裏面的元素是不能重複的。
5. 屬性爲map類型的屬性注入








map類型的鍵和值可以是任何類型,key-ref用來引用鍵是bean的,value-ref用來引用值是bean的
6. 屬性爲Properties類型的屬性注入



I LOVE YOU
I HATE YOU



Properties類型的元素爲props,每一個鍵值標籤是prop,注意要與property標籤進行區分。而且Properties類型的鍵和值必須都是String類型的。並且值是用標籤內容表示的,而不是用value屬性。
最後說一下匿名bean,這個比較少用。匿名bean跟匿名內部類是一樣的,但是匿名bean不需要實現接口,並且也只能用一次,所以標籤中不用寫id屬性。例如我們用匿名bean來作爲屬性注入時:
。匿名bean沒有id屬性,因爲匿名bean只能被使用一次,加上id屬性沒有意義。
好了,說到這裏,大家可以看到用xml裝配bean是一件很繁瑣的事情,而且我們還要找到對應類型的bean才能裝配。
首先,確定一下裝配的概念。《spring實戰》中給裝配下了一個定義:創建應用對象之間協作關係的行爲稱爲裝配。也就是說當一個對象的屬性是另一個對象時,實例化時,需要爲這個對象屬性進行實例化。這就是裝配。如果一個對象只通過接口來表明依賴關係,那麼這種依賴就能夠在對象本身毫不知情的情況下,用不同的具體實現進行切換。但是這樣會存在一個問題,在傳統的依賴注入配置中,我們必須要明確要給屬性裝配哪一個bean的引用,一旦bean很多,就不好維護了。基於這樣的場景,spring使用註解來進行自動裝配,解決這個問題。自動裝配就是開發人員不必知道具體要裝配哪個bean的引用,這個識別的工作會由spring來完成。與自動裝配配合的還有“自動檢測”,這 個動作會自動識別哪些類需要被配置成bean,進而來進行裝配。這樣我們就明白了,自動裝配是爲了將依賴注入“自動化”的一個簡化配置的操作。
裝配分爲四種:byName, byType, constructor, autodetect。byName就是會將與屬性的名字一樣的bean進行裝配。byType就是將同屬性一樣類型的bean進行裝配。constructor就是通過構造器來將類型與參數相同的bean進行裝配。autodetect是constructor與byType的組合,會先進行constructor,如果不成功,再進行byType。具體選擇哪一種裝配方式,需要配置標籤的autowire屬性,如果沒有配置,默認是byName類型,就是會根據屬性的名字來進行自動裝配。上面最常用的還是byName和byType。自動裝配時,裝配的bean必須是唯一與屬性進行吻合的,不能多也不能少,有且只有一個可以進行裝配的bean,才能自動裝配成功。否則會拋出異常。如果要統一所有bean的自動裝配類型,可以在標籤中配置default-autowire屬性。當然如果配置了autowire屬性,我們依然可以手動裝配屬性,手動裝配會覆蓋自動裝配。
以上是通過xml配置的方式實現自動裝配的,spring2.5之後提供了註解方式的自動裝配。但是要使用這些註解,需要在配置文件中配置<context:annotation-config />。只有加上這一配置,纔可以使用註解進行自動裝配,默認情況下基於註解的裝配是被禁用的。
常用的自動裝配註解有以下幾種:@Autowired,@Resource,@Inject,@Qualifier,@Named。@Autowired註解是byType類型的,這個註解可以用在屬性上面,setter方面上面以及構造器上面。使用這個註解時,就不需要在類中爲屬性添加setter方法了。但是這個屬性是強制性的,也就是說必須得裝配上,如果沒有找到合適的bean能夠裝配上,就會拋出異常。這時可以使用required=false來允許可以不被裝配上,默認值爲true。當required=true時,@Autowired要求必須裝配,但是在沒有bean能裝配上時,就會拋出異常:NoSuchBeanDefinitionException,如果required=false時,則不會拋出異常。另一種情況是同時有多個bean是一個類型的,也會拋出這個異常。此時需要進一步明確要裝配哪一個Bean,這時可以組合使用@Qualifier註解,值爲Bean的名字即可。@Qualifier註解使用byName進行裝配,這樣可以在多個類型一樣的bean中,明確使用哪一個名字的bean來進行裝配。@Qualifier註解起到了縮小自動裝配候選bean的範圍的作用。注意:@Autowired註解是spring提供的,所以會依賴spring的包。還有一個byType的註解@Inject,與@Autowired註解作用一樣,也是byType類型,而且是java ee提供的,完全可以代替@Autowired註解,但是@Inject必須是強制裝配的,沒有required屬性,也就是不能爲null,如果不存在匹配的bean,會拋出異常。@Autowired與@Qualifier可以組合使用,@Inject也有一個組合的註解,就是@Named註解,與@Qualifier作用一樣,也是byName,但是不是spring的,是java ee標準的。這樣就出現了兩套自動裝配的註解組合,@Autowired與@Qualifier是spring提供的,@Inject與@Named是java ee的。但是@Qualifier註解在java ee中也有一樣,作用與spring的@Qualifier註解一模一樣,只是所在的包不一樣。不過建議大家使用spring的。最後還有一個@Resouce註解, 這個註解也是java ee的,也是byName類型的,原理同@Qualifier和@Named是一樣的。
最後說一說,自動檢測配置,也是springmvc中最牛的一項功能。只要一個配置<context:component-scan base-package="">,base-package屬性指定要自動檢測掃描的包。
該配置會自動掃描指定的包及其子包下面被構造型註解標註的類,並將這些類註冊爲spring bean,這樣就不用在配置文件一個一個地配置成bean標籤。構造型註解包括:@Controller,@Components,@Service,@Repository和使用@Component標註的自定義註解。生成的bean的ID默認爲類的非限定名,也就是把類的名字的首字母換成小寫。可以在這些註解的值中寫名bean id的值,如@Controller(“helloworld”)。如果你想細化包被掃描的範圍,可以使用context:include-filtercontext:exclude-filter。具體使用方法這裏不再詳說。注意,沒有被掃描到的類是不能註冊爲bean,也就不能被用來裝配其他類。所以這個配置的base-package的範圍非常重要。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章