前文已經介紹了Spring Bean的生命週期,在這個週期內有一個重要的概念就是: IOC容器java
你們也知道IOC是Sping 的重要核心之一,那麼如何理解它呢,它又是產生什麼做用呢?本文就IOC原理進行簡要闡述。緩存
IoC 全稱爲 Inversion of Control
,翻譯爲 「控制反轉」,它還有一個別名爲 DI(Dependency Injection
),即依賴注入。安全
DI—Dependency Injection,即「依賴注入」:組件之間依賴關係由容器在運行期決定,形象的說,即由容器動態的將某個依賴關係注入到組件之中。ide
依賴注入的目的並不是爲軟件系統帶來更多功能,而是爲了提高組件重用的頻率,併爲系統搭建一個靈活、可擴展的平臺。性能
經過依賴注入機制,咱們只須要經過簡單的配置,而無需任何代碼就可指定目標須要的資源,完成自身的業務邏輯,而不須要關心具體的資源來自何處,由誰實現。this
如何理解「控制反轉」好呢?理解好它的關鍵在於咱們須要回答以下四個問題:spa
IoC和DI由什麼關係呢?其實它們是同一個概念的不一樣角度描述,因爲控制反轉概念比較含糊(可能只是理解爲容器控制對象這一個層面,很難讓人想到誰來維護對象關係),因此2004年大師級人物Martin Fowler又給出了一個新的名字:「依賴注入」,相對IoC 而言,「依賴注入」明確描述了「被注入對象依賴IoC容器配置依賴對象」。翻譯
以年輕小夥子找女友爲例子來講明IOC的做用:code
/** * 年輕小夥子 */ public class YoungMan { private BeautifulGirl beautifulGirl; YoungMan(){ // 可能你比較牛逼,指腹爲婚 // beautifulGirl = new BeautifulGirl(); } public void setBeautifulGirl(BeautifulGirl beautifulGirl) { this.beautifulGirl = beautifulGirl; } public static void main(String[] args){ YoungMan you = new YoungMan(); BeautifulGirl beautifulGirl = new BeautifulGirl("你的各類條件"); beautifulGirl.setxxx("各類投其所好"); // 而後你有女票了 you.setBeautifulGirl(beautifulGirl); } }
小夥子須要: new BeautifulGirl() ,也就是本身去建立一個女友對象。這個過程複雜而又繁瑣,並且咱們必需要面對每一個環節,同時使用完成以後咱們還要負責銷燬它。對象
小夥子本身不用去找女友,反過來找IOC,IOC就至關於一個婚介公司,它管理着不少男男女女的資料,小夥子直接跟婚介公司提出需求,婚介公司則會根據需求提供一個妹子給咱們,咱們只須要負責使用它就好了。
因此,簡單點說,IoC 的理念就是讓別人爲你服務
能夠理解爲: IOC主動把妹子注入給想使用它的小夥子。 (調用的時候使用Autowied ,這個對象就是前文說的bean, 經過註冊進入IOC容器,被實例化以後再進入IOC容器的bean緩存池,就能夠供程序調用了,這就和bean的生命週期連了起來。)
經過IOC的註冊機制能夠保證對象的安全性和合規性;
實例化對象只須要實例化一次,便可進入IOC容器的bean緩存池,下降了對象的建立開銷,提升了程序的性能(有點相似單例);
應用程序調用對象從bean緩存池獲取,這樣是秒獲取對象,提升了調用對象的速度。
如今來回答上面那四個問題,答案就顯得很是明顯了:
IOC Service Provider 爲被注入對象提供被依賴對象也有以下幾種方式:構造方法注入、stter方法注入、接口注入。
構造器注入
構造器注入,顧名思義就是被注入的對象經過在其構造方法中聲明依賴對象的參數列表,讓外部知道它須要哪些依賴對象。
YoungMan(BeautifulGirl beautifulGirl){ this.beautifulGirl = beautifulGirl; //這裏能夠定義不少女孩的條件 }
構造器注入方式比較直觀,對象構造完畢後就能夠直接使用,這就比如你出生你家裏就給你指定了你媳婦。
setter 方法注入
對於 JavaBean 對象而言,咱們通常都是經過 getter 和 setter 方法來訪問和設置對象的屬性。因此,當前對象只須要爲其所依賴的對象提供相對應的 setter 方法,就能夠經過該方法將相應的依賴對象設置到被注入對象中。以下:
public class YoungMan { private BeautifulGirl beautifulGirl; public void setBeautifulGirl(BeautifulGirl beautifulGirl) { this.beautifulGirl = beautifulGirl; } }
相比於構造器注入,setter 方式注入會顯得比較寬鬆靈活些,它能夠在任什麼時候候進行注入(固然是在使用依賴對象以前),這就比如你能夠先把本身想要的妹子想好了,而後再跟婚介公司打招呼,你能夠要林志玲款式的,趙麗穎款式的,隨意性較強。
通常程序中會使用這種方法進行實例化。
接口方式注入
接口方式注入顯得比較霸道,由於它須要被依賴的對象實現沒必要要的接口,帶有侵入性。通常都不推薦這種方式。
A對象須要使用合做對象B來共同完成一件事,A要使用B,那麼A就對B產生了依賴,也就是A和B之間存在一種耦合關係,而且是緊密耦合在一塊兒。
而使用了Spring以後就不同了,建立合做對象B的工做是由Spring來作的,Spring建立好B對象,而後存儲到一個容器裏面,當A對象須要使用B對象時,Spring就從存放對象的那個容器裏面取出A要使用的那個B對象,而後交給A對象使用,至於Spring是如何建立那個對象,以及何時建立好對象的,A對象不須要關心這些細節問題(你是何時生的,怎麼生出來的我可不關心,能幫我幹活就行),A獲得Spring給咱們的對象以後,兩我的一塊兒協做完成要完成的工做便可。
因此控制反轉IoC(Inversion of Control)是說建立對象的控制權進行轉移,之前建立對象的主動權和建立時機是由本身把控的,而如今這種權力轉移到第三方,好比轉移交給了IoC容器,它就是一個專門用來建立對象的工廠,你要什麼對象,它就給你什麼對象,有了 IoC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IoC容器了,經過IoC容器來創建它們之間的關係。