IoC模式最權威的總結和解釋,應該是Martin Fowler的那篇文章「Inversion of Control Containers and the Dependency Injection pattern」,其中提到了三種依賴注入的方式,即構造方法注入(constructor injection)、setter方法注入(setter injection)以及接口注入(interface injection)。下面讓咱們詳細看一下這三種方式的特色及其相互之間的差異。
ide
當你來到酒吧,想要喝杯啤酒的時候,一般會直接招呼服務生,「夥計,來杯啤酒!」,讓他爲你送來一杯清涼解渴的啤酒。一樣地,做爲被注入對象,要想讓IoC Service Provider爲其提供服務,並將所須要的被依賴對象送過來,也須要經過某種方式通知對方。this
(1)構造方法注入
顧名思義,構造方法注入,就是被注入對象能夠經過在其構造方法中聲明依賴對象的參數列表,讓外部(一般是IoC容器)知道它須要哪些依賴對象。例如:
spa
?.net
1
2
3
4
5
|
public
A(B b,C c)
{
this
.b = b;
this
.c = c;
}
|
IoC Service Provider會檢查被注入對象的構造方法,取得它所須要的依賴對象列表,進而爲其注入相應的對象。同一個對象是不可能被構造兩次的,所以,被注入對象的構造乃至其整個生命週期,應該是由IoC Service Provider來管理的。
構造方法注入方式比較直觀,對象被構造完成後,即進入就緒狀態,能夠立刻使用。
code
這就比如你剛進酒吧的門,服務生已經將你喜歡的啤酒擺上了桌面同樣。坐下就可立刻享受一份清涼與愜意。對象
(2)setter 方法注入 blog
對於JavaBean對象來講,一般會經過setXXX()和getXXX()方法來訪問對應屬性。這些setXXX()方法統稱爲setter方 法,getXXX()固然就稱爲getter方法。經過setter方法,能夠更改相應的對象屬性,經過getter方法,能夠得到相應屬性的狀態。所 以,當前對象只要爲其依賴對象所對應的屬性添加setter方法,就能夠經過setter方法將相應的依賴對象設置到被注入對象中。
繼承
?接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
class
A
{
private
B b;
private
C c;
public
B getb() {
return
b;
}
public
void
setb(B b) {
this
.b = b;
}
public
C getc() {
return
c;
}
public
void
setc(C c) {
this
.c = c;
}
}
|
這樣,外界就能夠經過調用setb和setc方法爲A對象注入所依賴的對象了。
setter方法注入雖不像構造方法注入那樣,讓對象構造完成後便可使用,但相對來講更寬鬆一些,能夠在對象構造完成後再注入。
生命週期
這就比如你能夠到酒吧坐下後再決定要點什麼啤酒,能夠要百威,也能夠要大雪,隨意性比較強。若是你不急着喝,這種方式固然是最適合你的。
(3)接口注入
相對於前兩種注入方式來講,接口注入沒有那麼簡單明瞭。
被注入對象若是想要IoC Service Provider爲其注入依賴對象,就必須實現某個接口。這個接口提供一個方法,用來爲其注入依賴對象。IoC Service Provider最終經過這些接口來了解應該爲被注入對象注入什麼依賴對象。
在這種狀況下,實現的接口和接口中聲明的方法名稱都不重要。重要的是接口中聲明方法的參數類型,必須是「被注入對象」所依賴對象的類型。
接口注入方式最先而且使用最多的是在一個叫作Avalon的項目中,相對於前兩種依賴注入方式,接口注入比較死板和煩瑣。
若是須要注入依賴對象,被注入對象就必須聲明和實現另外的接口。
這就好像你一樣在酒吧點啤酒,爲了讓服務生理解你的意思,你就必須戴上一頂啤酒杯式的帽子,看起來有點畫蛇添足。
一般狀況下,這有些讓人很差接受。不過,好在這種方式也能夠達到目的。
三種注入方式的比較
(1)接口注入。從注入方式的使用上來講,接口注入是如今不甚提倡的一種方式,基本處於「退役狀態」。由於它強制被注入對象實現沒必要要的接口,帶有侵入性。而構造方法注入和setter方法注入則不須要如此。
(2)構造方法注入。這種注入方式的優勢就是,對象在構造完成以後,即已進入就緒狀態,能夠立刻使用。缺點就是,當依賴對象比較多的時候,構造方法的參數 列表會比較長。而經過反射構造對象的時候,對相同類型的參數的處理會比較困難,維護和使用上也比較麻煩。並且在Java中,構造方法沒法被繼承,沒法設置 默認值。對於非必須的依賴處理,可能須要引入多個構造方法,而參數數量的變更可能形成維護上的不便。
(3)setter方法注入。由於方法能夠命名,因此setter方法注入在描述性上要比構造方法注入好一些。另外,setter方法能夠被繼承,容許設置默認值,並且有良好的IDE支持。缺點固然就是對象沒法在構造完成後立刻進入就緒狀態。
綜上所述,構造方法注入和setter方法注入由於其侵入性較弱,且易於理解和使用,因此是如今使用最多的注入方式;而接口注入由於侵入性較強,近年來已經不流行了。