提到spring,我們總會想到它的三大核心功能:spring的事務+AOP + IOC;小編已經在前面的博客陸續介紹了事務和AOP ,在這裏小編將與大家一起分享spring IOC上的理解和認識:
提到IOC,我們會想到依賴反轉,依賴注入兩個名詞,那麼什麼是反轉,用一句經典的話來說:Don't call us ,we will call you ! 當我們需要依賴某個類或者某個服務,最簡單有效的方法就是直接再累的構造函數中新建相應的依賴類即可;但是一定要這麼麻煩嗎??爲什麼每次用到依賴對象都要我們去主動獲取呢?這就引出了IOC的依賴發轉的概念,也就是說我們需要依賴某個對象的時候,不是我們主動,而是被依賴對象主動提供給我們相應的服務,而我們只是使用這個對象提供的某種服務,而絲毫不關心它是被別人送過來的還是我們主動獲取的!
所以實際上,IOC爲避免之前的“大費周折”,爲我們提供了更加輕鬆簡潔的方式,反轉你之前的“事必躬親”,轉爲現在的坐等服務,因此IOC的理念就是 讓別人爲你服務;也就是讓IOC service provider爲你服務;
在IOC場景中,被注入對象和被依賴對象通過IOC service provider 來打交道,所有被注入的對象和依賴對象會被該provider 同意管理,被注入的對象需要什麼,直接跟IOC service provider 招呼一聲,後者就會將相應的唄依賴對象注入到被注入對象中,從而達到IOC service provider爲被注入對象服務的目的。
所以IOC就是這麼簡單,但是作爲被注入對象,要想讓IOC service provider 爲其提供服務,並將所需要的被依賴對象送過來,也需要通過某種方式通知對象。主要是通過三種方式來通知:構造方法注入,setter方法注入,接口注入:
1.構造方法注入
顧名思義,構造方法注入,就是被注入對象可以通過在其構造方法中聲明依賴對象的參數列表,讓外部(通常是IoC容器)知道它需要哪些依賴對象。對於前面例子中的FXNewsProvider來說,只要聲明如下構造方法(見代碼清單2-3)即可支持構造方法注入。
public FXNewsProvider(IFXNewsListener newsListner,IFXNewsPersister newsPersister)
{
this.newsListener = newsListner;
this.newPersistener = newsPersister;
}<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal;">
</span></span>
IoC Service Provider會檢查被注入對象的構造方法,取得它所需要的依賴對象列表,進而爲其注入相應的對象。同一個對象是不可能被構造兩次的,因此,被注入對象的構造乃至其整個生命週期,應該是由IoC Service Provider來管理的。
2. setter方法注入
對於javaBean對象來說,通常通過set()和get()方法來訪問對應的屬性。這些set()方法統稱爲setter方法。通過setter()方法可以更改相應的對象屬性。所以當前對象只要爲其依賴對象所對應的屬性添加setter方法,就可以通過setter方法將相應的依賴對象設置到被注入對象中。
public class FXNewsProvider
{
private IFXNewsListener newsListener;
private IFXNewsPersister newPersistener;
public IFXNewsListener getNewsListener() {
return newsListener;
}
public void setNewsListener(IFXNewsListener newsListener) {
this.newsListener = newsListener;
}
public IFXNewsPersister getNewPersistener() {
return newPersistener;
}
public void setNewPersistener(IFXNewsPersister newPersistener) {
this.newPersistener = newPersistener;
}
}
這樣,外界就可以通過setNewsListener和setNewPersistener方法爲FXNewsProvider對象注入所依賴的對象了;
3. 接口注入
相對於前兩種注入方式來說,接口注入沒有那麼簡單明瞭。被注入對象如果想要IoC ServiceProvider爲其注入依賴對象,就必須實現某個接口。這個接口提供一個方法,用來爲其注入依賴對象。IoC Service Provider最終通過這些接口來了解應該爲被注入對象注入什麼依賴對象。圖 2-3演示瞭如何使用接口注入爲FXNewsProvider注入依賴對象。 FXNewsProvider爲了讓IoC Service Provider爲其注入所依賴的IFXNewsListener,首先需要實現IFXNewsListenerCallable接口,這個接口會聲明一個injectNewsListner方法(方法名隨意),該方法的參數,就是所依賴對象的類型。這樣, InjectionServiceContainer對象,即對應的IoCService Provider就可以通過這個接口方法將依賴對象注入到被注入對象FXNewsProvider當中。
相對於前兩種依賴注入的方式,接口注入比較死板和繁瑣,如果需要注入依賴對象,被注入對象就必須聲明和實現另外的接口。就像是在酒吧點啤酒,爲了讓服務生理解你的意思,你就必須戴上一頂啤酒杯式的帽子,看起來多此一舉;
總結:
1.構造方法注入:
2.setter方法注入
因爲方法可以命名, 所以setter方法注入在描述性上要比構造方法注入好一些。另外, setter方法可以被繼承,允許設置默認值,而且有良好的IDE支持。
缺點當然就是對象無法在構造完成後馬上進入就緒狀態。
3.接口注入
從注入方式的使用上來說,接口注入是現在不甚提倡的一種方式,基本處於“退役狀態”。因爲它強制被注入對象實現不必要的接口,帶有侵入性。而構造方法注入和setter方法注入則不需要如此。
不管是哪種注入方式,都有適合自己的使用場景,也都能幫我們實現注入,但是在實際編程中使用的時候,還是需要我們仔細辨別編程環境和各個注入方式的優缺點,選擇最恰當的注入方式,最大程度的發揮IOC容器給我們的便利!