學習過spring框架的人一定都會聽過Spring的IoC(控制反轉) 、DI(依賴注入)這兩個概念,對於初學Spring的人來說,總覺得IoC 、DI這兩個概念是模糊不清的,是很難理解的,今天和大家分享網上的一些技術大牛們對Spring框架的IOC的理解以及談談我對Spring Ioc的理解。
1、IOC是什麼
IOC—Inversion of Control,即“控制反轉”,不是什麼技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的物件交給容器控制,而不是傳統的在你的物件內部直接控制。
如何理解好Ioc呢?理解好Ioc的關鍵是要明確“誰控制誰,控制什麼,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:
誰控制誰,控制什麼: 傳統Java SE程式設計,我們直接在物件內部通過new進行建立物件,是程式主動去建立依賴物件;而IOC是有專門一個容器來建立這些物件,即由IOc容器來控制物件的建立而不再顯式地使用new;誰控制誰?當然是IOC容器控制了物件;控制什麼?那就是主要控制了外部資源獲取和生命週期(不只是物件也包括檔案等)。
為何是反轉,哪些方面反轉了: 有反轉就有正轉,傳統應用程式是由我們自己在物件中主動控制去直接獲取依賴物件,也就是正轉;而反轉則是由容器來幫忙建立及注入依賴物件;為何是反轉?因為由容器幫我們查詢及注入依賴物件,物件只是被動的接受依賴物件,所以是反轉;哪些方面反轉了?依賴物件的獲取被反轉了。
用圖例說明一下,傳統程式設計如圖1,都是主動去建立相關物件然後再組合起來:
當有了IOC的容器後,在客戶端類中不再主動去建立這些物件了,程式的結構圖變成如圖2所示:
2、IoC能做什麼
IOC不是一種技術,只是一種思想,一個重要的物件導向程式設計的法則,它能指導我們如何設計出鬆耦合、更優良的程式。傳統應用程式都是由我們在類內部主動建立依賴物件,從而導致類與類之間高耦合,難於測試;
有了IOC容器後,把建立和查詢依賴物件的控制權交給了容器,由容器進行注入組合物件,所以物件與物件之間是鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程式的整個體系結構變得非常靈活。
其實IOC對程式設計帶來的最大改變不是從程式碼上,而是從思想上,發生了“主從換位”的變化。應用程式原本是老大,要獲取什麼資源都是主動出擊,但是在IOC/DI思想中,應用程式就變成被動的了,被動的等待IOC容器來建立並注入它所需要的資源了。
IOC很好的體現了物件導向設計法則之一—— 好萊塢法則:“別找我們,我們找你”;即由IOC容器幫物件找相應的依賴物件並注入,而不是由物件主動去找。
3、IOC和DI
DI—Dependency Injection,即“依賴注入”:是元件之間依賴關係由容器在執行期決定,形象的說,即由容器動態的將某個依賴關係注入到元件之中。
依賴注入的目的並非為軟體系統帶來更多功能,而是為了提升元件重用的頻率,併為系統搭建一個靈活、可擴充套件的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何程式碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。
理解DI的關鍵是:“誰依賴誰,為什麼需要依賴,誰注入誰,注入了什麼”,那我們來深入分析一下:
誰依賴於誰:當然是應用程式依賴於IOC容器;
-
為什麼需要依賴:應用程式需要IOC容器來提供物件需要的外部資源;
-
誰注入誰:很明顯是IOC容器注入應用程式某個物件,應用程式依賴的物件;
-
注入了什麼:就是注入某個物件所需要的外部資源(包括物件、資源、常量資料)。
IOC和DI有什麼關係呢?其實它們是同一個概念的不同角度描述,由於控制反轉概念比較含糊(可能只是理解為容器控制物件這一個層面,很難讓人想到誰來維護物件關係),所以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”,相對IOC而言,“依賴注入”明確描述了“被注入物件依賴IOC容器配置依賴物件”。
看過很多對Spring的Ioc理解的文章,好多人對Ioc和DI的解釋都晦澀難懂,反正就是一種說不清,道不明的感覺,讀完之後依然是一頭霧水,看完這位技術牛人的部落格後有一種豁然開朗的研究,他清楚地解釋了IOC(控制反轉) 和DI(依賴注入)中的每一個字,讀完之後給人一種豁然開朗的感覺。我相信對於初學Spring框架的人對IOC的理解應該是有很大幫助的。
4、IOC和DI的意義
在平時的Java應用開發中,我們要實現某一個功能或者說是完成某個業務邏輯時至少需要兩個或以上的物件來協作完成,在沒有使用Spring的時候,每個物件在需要使用他的合作物件或者依賴物件時,自己均要使用像new object() 這樣的語法來將合作物件建立出來,這個合作物件是由自己主動建立出來的,建立合作物件的主動權在自己手上,自己需要哪個合作物件,就主動去建立,建立合作物件的主動權和建立時機是由自己把控的,而這樣就會使得物件間的耦合度高了,A物件需要使用合作物件B來共同完成一件事,A要使用B,那麼A就對B產生了依賴,也就是A和B之間存在一種耦合關係,並且是緊密耦合在一起。
而使用了Spring之後就不一樣了,建立合作物件B的工作是由Spring來做的,Spring建立好B物件,然後儲存到一個容器裡面,當A物件需要使用B物件時,Spring就從存放物件的那個容器裡面取出A要使用的那個B物件,然後交給A物件使用,至於Spring是如何建立那個物件,以及什麼時候建立好物件的,A物件不需要關心這些細節問題(你是什麼時候生的,怎麼生出來的我可不關心,能幫我幹活就行),A得到Spring給我們的物件B之後,兩個人一起協作完成要完成的工作即可。
所以控制反轉IOC(Inversion of Control)是說建立物件的控制權進行轉移,以前建立物件的主動權和建立時機是由自己把控的,而現在這種權力轉移到第三方,比如轉移交給了IOC容器,它就是一個專門用來建立物件的工廠,你要什麼物件,它就給你什麼物件,有了 IOC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IOC容器了,通過IOC容器來建立它們之間的關係。
DI(依賴注入)其實就是IOC的另外一種說法,DI是由Martin Fowler 在2004年初的一篇論文中首次提出的。他總結道:控制的什麼被反轉了?就是獲得依賴物件的方式反轉了。
原文參考公眾號【Java知音】