學(xué)習(xí)過Spring框架的人一定都會聽過Spring的IoC(控制反轉(zhuǎn)) 、DI(依賴注入)這兩個概念,對于初學(xué)Spring的人來說,總覺得IoC 、DI這兩個概念是模糊不清的,是很難理解的,今天和大家分享網(wǎng)上的一些技術(shù)大牛們對Spring框架的IOC的理解以及談?wù)勎覍pring Ioc的理解。 一、分享Iteye的開濤對Ioc的精彩講解首先要分享的是Iteye的開濤這位技術(shù)牛人對Spring框架的IOC的理解,寫得非常通俗易懂,以下內(nèi)容全部來自原文,原文地址:http://jinnianshilongnian./blog/1413846 1.1、IoC是什么Ioc—Inversion of Control,即“控制反轉(zhuǎn)”,不是什么技術(shù),而是一種設(shè)計思想。在Java開發(fā)中,Ioc意味著將你設(shè)計好的對象交給容器控制,而不是傳統(tǒng)的在你的對象內(nèi)部直接控制。如何理解好Ioc呢?理解好Ioc的關(guān)鍵是要明確“誰控制誰,控制什么,為何是反轉(zhuǎn)(有反轉(zhuǎn)就應(yīng)該有正轉(zhuǎn)了),哪些方面反轉(zhuǎn)了”,那我們來深入分析一下: ●誰控制誰,控制什么:傳統(tǒng)Java SE程序設(shè)計,我們直接在對象內(nèi)部通過new進行創(chuàng)建對象,是程序主動去創(chuàng)建依賴對象;而IoC是有專門一個容器來創(chuàng)建這些對象,即由Ioc容器來控制對 象的創(chuàng)建;誰控制誰?當(dāng)然是IoC 容器控制了對象;控制什么?那就是主要控制了外部資源獲?。ú恢皇菍ο蟀ū热缥募龋?/span>。 ●為何是反轉(zhuǎn),哪些方面反轉(zhuǎn)了:有反轉(zhuǎn)就有正轉(zhuǎn),傳統(tǒng)應(yīng)用程序是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉(zhuǎn);而反轉(zhuǎn)則是由容器來幫忙創(chuàng)建及注入依賴對象;為何是反轉(zhuǎn)?因為由容器幫我們查找及注入依賴對象,對象只是被動的接受依賴對象,所以是反轉(zhuǎn);哪些方面反轉(zhuǎn)了?依賴對象的獲取被反轉(zhuǎn)了。 用圖例說明一下,傳統(tǒng)程序設(shè)計如圖2-1,都是主動去創(chuàng)建相關(guān)對象然后再組合起來: 圖1-1 傳統(tǒng)應(yīng)用程序示意圖 當(dāng)有了IoC/DI的容器后,在客戶端類中不再主動去創(chuàng)建這些對象了,如圖2-2所示: 圖1-2有IoC/DI容器后程序結(jié)構(gòu)示意圖 1.2、IoC能做什么IoC 不是一種技術(shù),只是一種思想,一個重要的面向?qū)ο缶幊痰姆▌t,它能指導(dǎo)我們?nèi)绾卧O(shè)計出松耦合、更優(yōu)良的程序。傳統(tǒng)應(yīng)用程序都是由我們在類內(nèi)部主動創(chuàng)建依賴對象,從而導(dǎo)致類與類之間高耦合,難于測試;有了IoC容器后,把創(chuàng)建和查找依賴對象的控制權(quán)交給了容器,由容器進行注入組合對象,所以對象與對象之間是 松散耦合,這樣也方便測試,利于功能復(fù)用,更重要的是使得程序的整個體系結(jié)構(gòu)變得非常靈活。 其實IoC對編程帶來的最大改變不是從代碼上,而是從思想上,發(fā)生了“主從換位”的變化。應(yīng)用程序原本是老大,要獲取什么資源都是主動出擊,但是在IoC/DI思想中,應(yīng)用程序就變成被動的了,被動的等待IoC容器來創(chuàng)建并注入它所需要的資源了。 IoC很好的體現(xiàn)了面向?qū)ο笤O(shè)計法則之一—— 好萊塢法則:“別找我們,我們找你”;即由IoC容器幫對象找相應(yīng)的依賴對象并注入,而不是由對象主動去找。 1.3、IoC和DIDI—Dependency Injection,即“依賴注入”:組件之間依賴關(guān)系由容器在運行期決定,形象的說,即由容器動態(tài)的將某個依賴關(guān)系注入到組件之中。依賴注入的目的并非為軟件系統(tǒng)帶來更多功能,而是為了提升組件重用的頻率,并為系統(tǒng)搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業(yè)務(wù)邏輯,而不需要關(guān)心具體的資源來自何處,由誰實現(xiàn)。 理解DI的關(guān)鍵是:“誰依賴誰,為什么需要依賴,誰注入誰,注入了什么”,那我們來深入分析一下: ●誰依賴于誰:當(dāng)然是應(yīng)用程序依賴于IoC容器; ●為什么需要依賴:應(yīng)用程序需要IoC容器來提供對象需要的外部資源; ●誰注入誰:很明顯是IoC容器注入應(yīng)用程序某個對象,應(yīng)用程序依賴的對象; ●注入了什么:就是注入某個對象所需要的外部資源(包括對象、資源、常量數(shù)據(jù))。 IoC和DI由什么關(guān)系呢?其實它們是同一個概念的不同角度描述,由于控制反轉(zhuǎn)概念比較含糊(可能只是理解為容器控制對象這一個層面,很難讓人想到誰來維護對象關(guān)系),所以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”,相對IoC 而言,“依賴注入”明確描述了“被注入對象依賴IoC容器配置依賴對象”。 看過很多對Spring的Ioc理解的文章,好多人對Ioc和DI的解釋都晦澀難懂,反正就是一種說不清,道不明的感覺,讀完之后依然是一頭霧水,感覺就是開濤這位技術(shù)牛人寫得特別通俗易懂,他清楚地解釋了IoC(控制反轉(zhuǎn)) 和DI(依賴注入)中的每一個字,讀完之后給人一種豁然開朗的感覺。我相信對于初學(xué)Spring框架的人對Ioc的理解應(yīng)該是有很大幫助的。 二、分享Bromon的blog上對IoC與DI淺顯易懂的講解2.1、IoC(控制反轉(zhuǎn))首先想說說IoC(Inversion of Control,控制反轉(zhuǎn))。這是spring的核心,貫穿始終。所謂IoC,對于spring框架來說,就是由spring來負責(zé)控制對象的生命周期和對象間的關(guān)系。這是什么意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪里有長得漂亮身材又好的mm,然后打聽她們的興趣愛好、qq號、電話號、ip號、iq號………,想辦法認識她們,投其所好送其所要,然后嘿嘿……這個過程是復(fù)雜深奧的,我們必須自己設(shè)計和面對每個環(huán)節(jié)。傳統(tǒng)的程序開發(fā)也是如此,在一個對象中,如果要使用另外的對象,就必須得到它(自己new一個,或者從JNDI中查詢一個),使用完之后還要將對象銷毀(比如Connection等),對象始終會和其他的接口或類藕合起來。 那么IoC是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個列表,告訴它我想找個什么樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周杰倫,速度像卡洛斯,技術(shù)像齊達內(nèi)之類的,然后婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛、結(jié)婚就行了。簡單明了,如果婚介給我們的人選不符合要求,我們就會拋出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構(gòu)來控制。Spring所倡導(dǎo)的開發(fā)方式就是如此,所有的類都會在spring容器中登記,告訴spring你是個什么東西,你需要什么東西,然后spring會在系統(tǒng)運行到適當(dāng)?shù)臅r候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的創(chuàng)建、銷毀都由 spring來控制,也就是說控制對象生存周期的不再是引用它的對象,而是spring。對于某個具體的對象而言,以前是它控制其他對象,現(xiàn)在是所有對象都被spring控制,所以這叫控制反轉(zhuǎn)。 2.2、DI(依賴注入)IoC的一個重點是在系統(tǒng)運行中,動態(tài)的向某個對象提供它所需要的其他對象。這一點是通過DI(Dependency Injection,依賴注入)來實現(xiàn)的。比如對象A需要操作數(shù)據(jù)庫,以前我們總是要在A中自己編寫代碼來獲得一個Connection對象,有了 spring我們就只需要告訴spring,A中需要一個Connection,至于這個Connection怎么構(gòu)造,何時構(gòu)造,A不需要知道。在系統(tǒng)運行時,spring會在適當(dāng)?shù)臅r候制造一個Connection,然后像打針一樣,注射到A當(dāng)中,這樣就完成了對各個對象之間關(guān)系的控制。A需要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這么來的。那么DI是如何實現(xiàn)的呢? Java 1.3之后一個重要特征是反射(reflection),它允許程序在運行的時候動態(tài)的生成對象、執(zhí)行對象的方法、改變對象的屬性,spring就是通過反射來實現(xiàn)注入的。 理解了IoC和DI的概念后,一切都將變得簡單明了,剩下的工作只是在spring的框架中堆積木而已。 三、我對IoC(控制反轉(zhuǎn))和DI(依賴注入)的理解在平時的java應(yīng)用開發(fā)中,我們要實現(xiàn)某一個功能或者說是完成某個業(yè)務(wù)邏輯時至少需要兩個或以上的對象來協(xié)作完成,在沒有使用Spring的時候,每個對象在需要使用他的合作對象時,自己均要使用像new object() 這樣的語法來將合作對象創(chuàng)建出來,這個合作對象是由自己主動創(chuàng)建出來的,創(chuàng)建合作對象的主動權(quán)在自己手上,自己需要哪個合作對象,就主動去創(chuàng)建,創(chuàng)建合作對象的主動權(quán)和創(chuàng)建時機是由自己把控的,而這樣就會使得對象間的耦合度高了,A對象需要使用合作對象B來共同完成一件事,A要使用B,那么A就對B產(chǎn)生了依賴,也就是A和B之間存在一種耦合關(guān)系,并且是緊密耦合在一起,而使用了Spring之后就不一樣了,創(chuàng)建合作對象B的工作是由Spring來做的,Spring創(chuàng)建好B對象,然后存儲到一個容器里面,當(dāng)A對象需要使用B對象時,Spring就從存放對象的那個容器里面取出A要使用的那個B對象,然后交給A對象使用,至于Spring是如何創(chuàng)建那個對象,以及什么時候創(chuàng)建好對象的,A對象不需要關(guān)心這些細節(jié)問題(你是什么時候生的,怎么生出來的我可不關(guān)心,能幫我干活就行),A得到Spring給我們的對象之后,兩個人一起協(xié)作完成要完成的工作即可。 所以控制反轉(zhuǎn)IoC(Inversion of Control)是說創(chuàng)建對象的控制權(quán)進行轉(zhuǎn)移,以前創(chuàng)建對象的主動權(quán)和創(chuàng)建時機是由自己把控的,而現(xiàn)在這種權(quán)力轉(zhuǎn)移到第三方,比如轉(zhuǎn)移交給了IoC容器,它就是一個專門用來創(chuàng)建對象的工廠,你要什么對象,它就給你什么對象,有了 IoC容器,依賴關(guān)系就變了,原先的依賴關(guān)系就沒了,它們都依賴IoC容器了,通過IoC容器來建立它們之間的關(guān)系。 這是我對Spring的IoC(控制反轉(zhuǎn))的理解。DI(依賴注入)其實就是IOC的另外一種說法,DI是由Martin Fowler 在2004年初的一篇論文中首次提出的。他總結(jié):控制的什么被反轉(zhuǎn)了?就是:獲得依賴對象的方式反轉(zhuǎn)了。 四、小結(jié)對于Spring Ioc這個核心概念,我相信每一個學(xué)習(xí)Spring的人都會有自己的理解。這種概念上的理解沒有絕對的標準答案,仁者見仁智者見智。如果有理解不到位或者理解錯的地方,歡迎廣大園友指正! |
|