1、IoC的理念
IoC全稱為Inversion of Control,中文翻譯為控制反轉,同時還有一個別名叫 依賴注入DI(Dependency Injection),大多將IoC與DI看作同等概念,也有部分觀點認為 依賴注入可以看作IoC的一種實作方式,
在沒有Spring的時候,當我們需要依賴某個類或服務時,一般通過new創建一個物件(或者通過ServiceLocator解決直接的依賴耦合),這些都需要主動的去獲取需要的物件,
ServiceLocator是通過引入中間代理者消除物件間復雜的耦合關系,并統一管理分散的復雜耦合關系,
IoC的出現就為我們提供了更加簡潔的方式,不用主動去構造物件,將“主動獲取”轉變為“被動接收”,下圖即為IoC在整個程序中的所承擔的角色

通常情況下,被注入物件會直接依賴于被依賴物件,但是在IoC的場景中,二者通過IoC Service Provider來互動,全部由IoC Service Provider統一管理,控制權由被注入物件轉變為了IoC Service Provider 那里,
public class NewsProvider {
// NewsProvider 為被注入物件
// INewsListener和INewsPersister為被依賴物件
private INewsListener newsListener;
private INewsPersister newsPersister;
}
其實IoC就是這么簡單!以前是需要什么自己去拿,現在是需要什么東西別人主動送過來,下圖形象的說明了使用IoC模式的前后差別

2、IoC(DI)的幾種依賴注入的方式
IoC模式最常用的有三種依賴注入方式,分別是構造方法注入(Constructor Injection)、setter方法注入(Setter Injection)以及介面注入(Interface Injection),
2.1、構造方法注入
構造方法注入即 被注入物件可以通過在其構造方法中宣告所依賴物件的引數串列,讓IoC容器知道它所需要的依賴物件串列,由于同一個物件是不可能是被構造兩次的,因此,被注入物件的構造乃至其整個生命周期,都是由IoC Service Provider來管理的,
IoC Service Provider會檢查被注入物件的構造方法,取得它所需要的依賴物件串列,進而為其注入相應的物件,具體代碼示例如下
public class NewsProvider {
// NewsProvider 為被注入物件
// INewsListener和INewsPersister為被依賴物件
private INewsListener newsListener;
private INewsPersister newsPersister;
public NewsProvider(INewsListener newsListener, INewsPersister newsPersister) {
this.newsListener = newsListener;
this.newsPersister = newsPersister;
}
}
構造方法注入的方式比較直觀,物件被構造完成后,就進入了就緒裝填,可以馬上使用,
2.2、setter方法注入
對于JavaBean物件來說,通常會通過setter方法來更改相應的物件屬性,所以,當前物件只要為其依賴物件所對應的屬性添加setter方法,就可以通過setter方法將相應的依賴物件設定到被注入物件中,代碼示例如下
public class NewsProvider {
// NewsProvider 為被注入物件
// INewsListener和INewsPersister為被依賴物件
private INewsListener newsListener;
private INewsPersister newsPersister;
public void setNewsListener(INewsListener newsListener) {
this.newsListener = newsListener;
}
public void setNewsPersister(INewsPersister newsPersister) {
this.newsPersister = newsPersister;
}
}
這樣,外界就可以通過呼叫setNewsListener和setNewsPersister方法來注入依賴物件了,
需要注意的是,setter方法注入不像構造方法注入那樣,物件構造完成后即可使用,相對而言更加寬松一些,可以在物件構造完成之后再注入,
2.3、介面注入(基本廢棄)
相對前面的兩種注入方式來說,介面注入會更加復雜,被注入物件如果想讓IoC Service Provider為其注入依賴物件,就必須實作某個介面,這個介面提供一個方法,用來為其注入依賴物件,IoC Service Provider 最侄訓通過這些介面來獲取被注入物件所需要的依賴物件串列,
NewsProvicer為了讓IoC Service Provider 為其注入所依賴的NewsListener物件,首先需要實作一個介面 INewsListenerCallable(名稱隨意),這個介面會宣告一個injectNewsListener方法(名稱隨意),重要的是該方法的引數,必須是所依賴物件的型別,這樣,對應的IoC Service Provider 就可以通過這個介面方法將依賴物件注入到 被注入物件 NewsProvider 當中,代碼示例如下,
public interface NewsListenerCallable {
// 宣告方法
void injectNewsListener(INewsListener newsListener);
}
public class NewsProvider implements NewsListenerCallable{
private INewsListener newsListener;
@Override
public void injectNewsListener(INewsListener newsListener) {
this.newsListener = newsListener;
}
}
2.3、三種注入方式的比較
- 構造方法注入,這種注入方式的優點就是,物件在構造完成之后,就已進入就緒狀態,可以馬上使用,缺點就是,當依賴物件變多時,構造方法的引數串列會比較長,同時通過反射構造物件時,對相同型別的引數處理會比較困難,維護和使用上也比較麻煩,而且在Java中,構造方法無法被繼承,無法設定默認值,對于非必須的依賴處理,可能還需要引入多個構造方法,維護不便,
- setter方法注入,優點就是,在描述性上會比構造方法注入要好,同時可以被繼承,允許設定默認值,而且有良好的IDE支持,缺點就是物件無法在構造完成后立馬進入就緒狀態,
- 介面注入,從注入方式的使用上來說,介面注入是目前不提倡的一種方法,基本處于“退役狀態”,因為需要被注入物件實作不必要的介面,帶有侵入性,
綜上,構造方法注入和setter注入因為其侵入性較弱,且易于理解和使用,所以是現在使用最多的注入方式;而介面注入由于其侵入性,已經不流行了,
本文由博客一文多發平臺 OpenWrite 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/549611.html
標籤:Java
上一篇:中小型專案請求限流設計
