IoC(控制反轉) 和DI(依賴注入)
首先:第一個問題,參與者都有誰?
1)物件 2)IOC/DI容器 3)某個物件的外部資源第二問題:依賴,誰依賴誰?為什麼需要依賴? 依賴嘛,很好理解的,物件依賴於IOC/DI容器,至於為什麼要依賴呢?物件需要IOC/DI容器來提供物件需要的外部資源。第三個問題:注入,誰注入誰?又注入了什麼呢? 顯而易見是IOC/DI容器注入物件,注入了what呢?肯定注入的是某個需要的東西那就是注入物件所需要的資源,肯定不會注入無關緊要的內容,你說呢?第四個問題:控制反轉,誰控制誰?控制什麼?為什麼叫反轉呢?存在正轉嗎? 控制反轉,控制什麼?肯定是IOC/DI容器控制物件,主要是控制物件例項的建立,反轉是相對於正向而言的,那麼什麼算是正向的呢?考慮一下常規情況下的應用程式,如果要在A裡面使用C,你會怎麼做呢?當然是直接去建立C的物件,也就是說,是在A類中主動去獲取所需要的外部資源C,這種情況被稱為正向的。那麼什麼是反向呢?就是A類不再主動去獲取C,而是被動等待,等待IoC/DI的容器獲取一個C的例項,然後反向的注入到A類中。第五個問題:控制反轉和依賴注入式同一個概念嗎?
1.1、IoC是什麼
Ioc—Inversion of Control,即“控制反轉”,不是什麼技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的物件交給容器控制,而不是傳統的在你的物件內部直接控制。
●誰控制誰,控制什麼:傳統Java SE程式設計,我們直接在物件內部通過new進行建立物件,是程式主動去建立依賴物件;而IoC是有專門一個容器來建立這些物件,即由Ioc容器來控制對 象的建立;誰控制誰?當然是IoC 容器控制了物件;控制什麼?那就是主要控制了外部資源獲取(不只是物件包括比如檔案等)。
●為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程式是由我們自己在物件中主動控制去直接獲取依賴物件,也就是正轉;而反轉則是由容器來幫忙建立及注入依賴物件;為何是反轉?因為由容器幫我們查詢及注入依賴物件,物件只是被動的接受依賴物件,所以是反轉;哪些方面反轉了?依賴物件的獲取被反轉了。
1.2、IoC能做什麼
IoC 不是一種技術,只是一種思想,一個重要的面向物件程式設計的法則,它能指導我們如何設計出鬆耦合、更優良的程式。傳統應用程式都是由我們在類內部主動建立依賴物件,從而導致類與類之間高耦合,難於測試;有了IoC容器後,把建立和查詢依賴物件的控制權交給了容器,由容器進行注入組合物件,所以物件與物件之間是 鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程式的整個體系結構變得非常靈活。
其實IoC對程式設計帶來的最大改變不是從程式碼上,而是從思想上,發生了“主從換位”的變化。應用程式原本是老大,要獲取什麼資源都是主動出擊,但是在IoC/DI思想中,應用程式就變成被動的了,被動的等待IoC容器來建立並注入它所需要的資源了。
IoC很好的體現了面向物件設計法則之一—— 好萊塢法則:“別找我們,我們找你”;即由IoC容器幫物件找相應的依賴物件並注入,而不是由物件主動去找。
1.3、IoC和DI
DI—Dependency Injection,即“依賴注入”:元件之間依賴關係由容器在執行期決定,形象的說,即由容器動態的將某個依賴關係注入到元件之中。依賴注入的目的並非為軟體系統帶來更多功能,而是為了提升元件重用的頻率,併為系統搭建一個靈活、可擴充套件的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何程式碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。
理解DI的關鍵是:“誰依賴誰,為什麼需要依賴,誰注入誰,注入了什麼”,那我們來深入分析一下:
●誰依賴於誰:當然是應用程式依賴於IoC容器;
●為什麼需要依賴:應用程式需要IoC容器來提供物件需要的外部資源;
●誰注入誰:很明顯是IoC容器注入應用程式某個物件,應用程式依賴的物件;
●注入了什麼:就是注入某個物件所需要的外部資源(包括物件、資源、常量資料)。
IoC和DI由什麼關係呢?其實它們是同一個概念的不同角度描述,由於控制反轉概念比較含糊(可能只是理解為容器控制物件這一個層面,很難讓人想到誰來維護物件關係),所以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”,相對IoC 而言,“依賴注入”明確描述了“被注入物件依賴IoC容器配置依賴物件”。
二、分享Bromon的blog上對IoC與DI淺顯易懂的講解
2.1、IoC(控制反轉)
首先想說說IoC(Inversion of Control,控制反轉)。這是spring的核心,貫穿始終。所謂IoC,對於spring框架來說,就是由spring來負責控制物件的生命週期和物件間的關係。這是什麼意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪裡有長得漂亮身材又好的mm,然後打聽她們的興趣愛好、qq號、電話號、ip號、iq號………,想辦法認識她們,投其所好送其所要,然後嘿嘿……這個過程是複雜深奧的,我們必須自己設計和麵對每個環節。傳統的程式開發也是如此,在一個物件中,如果要使用另外的物件,就必須得到它(自己new一個,或者從JNDI中查詢一個),使用完之後還要將物件銷燬(比如Connection等),物件始終會和其他的介面或類藕合起來。
那麼IoC是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個列表,告訴它我想找個什麼樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周杰倫,速度像卡洛斯,技術像齊達內之類的,然後婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛、結婚就行了。簡單明瞭,如果婚介給我們的人選不符合要求,我們就會丟擲異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。Spring所倡導的開發方式就是如此,所有的類都會在spring容器中登記,告訴spring你是個什麼東西,你需要什麼東西,然後spring會在系統執行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的建立、銷燬都由 spring來控制,也就是說控制物件生存週期的不再是引用它的物件,而是spring。對於某個具體的物件而言,以前是它控制其他物件,現在是所有物件都被spring控制,所以這叫控制反轉。
2.2、DI(依賴注入)
IoC的一個重點是在系統執行中,動態的向某個物件提供它所需要的其他物件。這一點是通過DI(Dependency Injection,依賴注入)來實現的。比如物件A需要操作資料庫,以前我們總是要在A中自己編寫程式碼來獲得一個Connection物件,有了 spring我們就只需要告訴spring,A中需要一個Connection,至於這個Connection怎麼構造,何時構造,A不需要知道。在系統執行時,spring會在適當的時候製造一個Connection,然後像打針一樣,注射到A當中,這樣就完成了對各個物件之間關係的控制。A需要依賴 Connection才能正常執行,而這個Connection是由spring注入到A中的,依賴注入的名字就這麼來的。那麼DI是如何實現的呢? Java 1.3之後一個重要特徵是反射(reflection),它允許程式在執行的時候動態的生成物件、執行物件的方法、改變物件的屬性,spring就是通過反射來實現注入的。
理解了IoC和DI的概念後,一切都將變得簡單明瞭,剩下的工作只是在spring的框架中堆積木而已。所以控制反轉IoC(Inversion of Control)是說建立物件的控制權進行轉移,以前建立物件的主動權和建立時機是由自己把控的,而現在這種權力轉移到第三方,比如轉移交給了IoC容器,它就是一個專門用來建立物件的工廠,你要什麼物件,它就給你什麼物件,有了 IoC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IoC容器了,通過IoC容器來建立它們之間的關係。
轉載自: