控制反轉

1起源

早 在2004年,Martin Fowler就提出了「哪些方面的控制被反轉了?」這個問題。他總結出是依賴對象的得到被反轉了。基於這個結論,他爲控制反轉創造了一個更好的名字:依賴 注入。 許多非凡的應用(比HelloWorld.java更加優美,更加複雜)都是由兩個或是更多的類經過彼此的合做來實現業務邏輯,這使得每一個對象都需 要,與其合做的對象(也就是它所依賴的對象)的引用。若是這個獲取過程要靠自身實現,那麼如你所見,這將致使代碼高度耦合而且難以測試。
IoC 亦稱爲 「依賴倒置原理」("Dependency Inversion Principle")。差很少全部 框架都使用了「倒置注入(Fowler 2004)技巧,這可說是IoC原理的一項應用。SmallTalk,C++, Java 或各類.NET 語言等 面向對象程序語言的 程序員已使用了這些原理。
控制反轉是 Spring框架的核心。

應用控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體,將其所依賴的對象的引用,傳遞給它。也能夠說,依賴被注入到對象中。因此,控制反轉是,關於一個對象如何獲取他所依賴的對象的引用,這個責任的反轉。 java

2設計模式

IoC就是IoC,不是什麼技術,與 GoF同樣,是一種 設計模式
Interface Driven Design接口驅動,接口驅動有不少好處,能夠提供不一樣靈活的子類實現,增長代碼穩定和健壯性等等,可是接口必定是須要實現的,也就是以下語句早晚要執 行:AInterface a = new AInterfaceImp(); 這樣一來,耦合關係就產生了,如:
1
2
3
4
5
6
7
8
9

Class A
{
    AInterface a;
    A() { }
    aMethod()
    {
        a =newAInterfaceImp();
    }
}
ClassA與AInterfaceImp就是依賴關係,若是想使用AInterface的另一個實現就須要更改代碼了。固然咱們能夠創建一個Factory來根據條件生成想要的AInterface的具體實現,即:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
InterfaceImplFactory
{
    AInterface create(Object condition)
    {
        if(condition = condA)
        {
            returnnewAInterfaceImpA();
        }
        elseif(condition = condB)
        {
            returnnewAInterfaceImpB();
        }
        else
        {
            returnnewAInterfaceImp();
        }
    }
}
表面上是在必定程度上緩解了以上問題,但實質上這種代碼耦合並無改變。經過IoC模式能夠完全解決這種耦合,它把耦合從代碼中移出去,放到統一的XML 文件中, 經過一個容器在須要的時候把這個依賴關係造成,即把須要的接口實現注入到須要它的類中,這可能就是「依賴注入」說法的來源
IOC模式,系統中經過引入實現了IOC模式的IOC容器,便可由IOC容器來管理對象的生命週期、依賴關係等,從而使得 應用程序的配置和依賴性規範與實際的應用程序代碼分開。其中一個特色就是經過 文本的配置文件進行 應用程序組件間相互關係的配置,而不用從新修改並編譯具體的代碼。
當前比較知名的IOC容器有:Pico Container、Avalon 、Spring、JBoss、HiveMind、EJB等。

在上面的幾個IOC容器中,輕量級的有Pico Container、Avalon、Spring、HiveMind等,超重量級的有EJB,而半輕半重的有容器有JBoss,Jdon等。 程序員

能夠把IoC模式看作是工廠模式的昇華,能夠把IoC看做是一個大工廠,只不過這個大工廠裏要生成的對象都是在XML文件中給出定義的,而後利用Java 的「反射」編程,根據XML中給出的類名生成相應的對象。從實現來看,IoC是把之前在工廠方法裏寫死的對象生成代碼,改變爲由XML文件來定義,也就是 把工廠和對象生成這二者獨立分隔開來,目的就是提升靈活性和可維護性。
IoC中最基本的Java技術就是「反射」編程。反射又是一個生澀的名詞,通俗的說反射就是根據給出的類名(字符串)來生成對象。這種 編程方式可讓對象在生成時才決定要生成哪種對象。反射的應用是很普遍的,象Hibernate、Spring中都是用「反射」作爲最基本的技術手段。
在過去,反射編程方式相對於正常的對象生成方式要慢10幾倍,這也許也是當時爲何 反射技術沒有普通應用開來的緣由。但經SUN改良優化後,反射方式生成對象和一般對象生成方式,速度已經相差不大了(但依然有一倍以上的差距)。

3優缺點

IoC最大的好處是什麼?由於把對象生成放在了XML裏定義,因此當咱們須要換一個實現子類將會變成很簡單(通常這樣的對象都是實現於某種接口的),只要修改XML就能夠了,這樣咱們甚至能夠實現對象的熱插撥(有點象USB接口和SCSI硬盤了)。

IoC最大的缺點是什麼?(1)生成一個對象的步驟變複雜了(事實上操做上仍是挺簡單的),對於不習慣這種方式的 人,會以爲有些彆扭和不直觀。(2)對象生成由於是使用反射編程,在效率上有些損耗。但相對於IoC提升的維護性和靈活性來講,這點損耗是微不足道的,除 非某對象的生成對效率要求特別高。(3)缺乏IDE重構操做的支持,若是在Eclipse要對類更名,那麼你還須要去XML文件裏手工去改了,這彷佛是所 有XML方式的缺憾所在。 編程

4實現初探

IOC關注服務(或 應用程序部件)是如何定義的以及他們應該如何定位他們依賴的其它服務。一般,經過一個容器或定位框架來得到定義和定位的分離,容器或定位框架負責:
保存可用服務的集合
提供一種方式將各類部件與它們依賴的服務綁定在一塊兒
應用程序代碼提供一種方式來請求已配置的對象(例如,一個全部依賴都知足的對象), 這種方式能夠確保該對象須要的全部相關的服務均可用。

5類型

現有的 框架實際上使用如下三種基本技術的框架執行服務和部件間的綁定:
類型1 (基於接口): 可服務的對象須要實現一個專門的接口,該接口提供了一個對象,能夠從用這個對象查找依賴(其它服務)。早期的容器Excalibur使用這種模式。
類型2 (基於setter): 經過JavaBean的屬性(setter方法)爲可服務對象指定服務。HiveMind和Spring採用這種方式。

類型3 (基於構造函數): 經過構造函數的參數爲可服務對象指定服務。PicoContainer只使用這種方式。HiveMind和Spring也使用這種方式。 設計模式

6實現策略

IoC是一個很大的概念,能夠用不一樣的方式實現。其主要形式有兩種:
依賴查找:容器提供回調接口和上下文條件給組件。EJB和Apache Avalon 都使用這種方式。這樣一來,組件就必須使用容器提供的API來查找資源和協做對象,僅有的控制反轉只體如今那些回調方法上(也就是上面所說的 類型1):容器將調用這些回調方法,從而讓應用代碼得到相關資源。
依賴注入:組件不作定位查詢,只提供普通的Java方法讓容器去決定依賴關係。容器全權負責的組件的裝配,它會把符合依賴關係的對象經過JavaBean屬性或者 構造函數傳遞給須要的對象。經過JavaBean屬性注射依賴關係的作法稱爲設值方法注入(Setter Injection);將依賴關係做爲 構造函數參數傳入的作法稱爲 構造子注入(Constructor Injection)
相關文章
相關標籤/搜索