相信在面試中,只要問到Spring,基本都會拋出一個問題,說說你對Spring IOC理解吧?雖然在平常的開發常常會使用到,可是要回答起來,並不簡單。大腦通過簡單的頭腦風暴後,蹦出了控制反轉、依賴注入這樣的詞語。顯然這些並非面試官想聽的。java
IOC(Inverse of Contro)控制反轉,有時候也被稱爲DI(Dependency injection)依賴注入,它是一種下降對象耦合關係的一種設計思想。web
2004年,Martin Fowler探討了一個問題,既然IOC是控制反轉,那麼究竟是哪些方面的控制被反轉了呢?,通過詳細地分析和論證後,他得出了答案:得到依賴對象的過程被反轉了。控制被反轉以後,得到依賴對象的過程由自身管理變爲了由IOC容器主動注入。因而,他給「控制反轉」取了一個更合適的名字叫作「依賴注入(Dependency Injection)」。他的這個答案,實際上給出了實現IOC的方法:注入。所謂依賴注入就是:由IOC容器在運行期間,動態地將某種依賴關係注入到對象之中。面試
控制反轉(IOC)是一種思想,而依賴注入(Dependency Injection)則是實現這種思想的方法。app
假若有這樣一個場景,你一時興起你想玩GTA5
,這時候你須要先去下載GTA5
,而後安裝好GTA5
,安裝完之後你就能開心的玩耍了。玩了一段時間你能夠能以爲有點膩了,又想玩CS
了,很顯然你又要先去下載,而後安裝,才能愉快的玩耍。多經歷幾回,你可能就以爲有點煩了,你就在想要是有個遊戲倉庫就行了,能自動的幫我下載和安裝遊戲。這樣我想玩啥,遊戲倉庫直接給我就能夠了。而IOC
就是這個遊戲倉庫。ide
Gamethis
public interface Game {
void download();
void install();
void play();
}
複製代碼
Csspa
public class Cs implements Game {
@Override
public void download() {
System.out.println("下載Cs");
}
@Override
public void install() {
System.out.println("安裝Cs");
}
@Override
public void play() {
System.out.println("我在玩Cs");
}
}
複製代碼
Gta5.net
public class Gta5 implements Game {
@Override
public void download() {
System.out.println("下載GTA5");
}
@Override
public void install() {
System.out.println("安裝GTA5");
}
@Override
public void play() {
System.out.println("GTA5玩的很開心");
}
}
複製代碼
Player翻譯
public class Player {
public void play(){
Game game = new Gta5();
game.download();
game.install();
game.play();
}
}
複製代碼
上面代碼中能夠看到Player
和Gta5
(這能夠是任意一個實現了Game接口
的類型)之間存在強耦合關係,而且在編譯期間就指定好了。當Gta5
發生改變時,Player
也須要作出相應的改變。因爲每一個玩家玩的遊戲都是不同的,若是要適應需求,那咱們須要不停的進行修改。顯然這是不符合規範的。設計
public class Player {
private Game game;.
public Player(Game game) {
this.game = game;
}
public void play(){
game.play();
}
}
複製代碼
將Player
的代碼根據依賴倒置原則
,程序要依賴於抽象接口,不要依賴於具體實現進行修改。這樣大大下降了Player
和具體Game的實現類
的耦合度。這個時候咱們能夠發現,本來須要在Player
內對Game
具體實現類進行實例化,如今變成了由外部傳入。假如我傳個Gat5
進去,他就在玩Gta5
,把Gta5
變成Cs
,他就在玩Cs
了。Player
不須要進行任何改變。
這個時候,咱們再回過頭來看看的定義。
本來呢,我想玩遊戲,我必需要先去下載好遊戲,等到安裝完成之後,才能開始玩。有了遊戲倉庫之後,我只須要告訴它,我玩啥遊戲就能夠了,它就會幫我下載並安裝好遊戲,等到我想玩的時候就能直接玩了。
本來呢,我須要在Player
內本身的去實例化Game
的實現類。如今呢,只須要在XML
內配置好相應的依賴關係。假如配置的是Gta5
。等到Player
被實例化的時候,IOC
就會將Gta5
注入進來了。至於Gta5
是如何被實例化的Player
徹底不須要關心。
歸納一下:就是主動建立對象過程變成了被動接收,編譯期依賴變成了運行時依賴,從而達到了對象之間的鬆耦合。
很顯然,IOC的做用是下降對象和對象之間的耦合度,這和咱們所指望高內聚,低耦合的設計思想是一致的嘛,因此能下降耦合固然要使用啊。好處有以下幾點:
不知道會不會有小夥伴吐槽,看了半天IOC不就是個工廠嘛,都是將類實例化的過程透明化,方便調用方使用。其實仍是有所區別。當需求發生改變的時候,工廠模式須要修改相應的類才能實現,然而IOC是經過反射機制來實現的,不須要咱們從新編譯代碼,由於它的對象都是動態生成的。
舉個簡單的例子,假如xx類的構造參數發生改變了,工廠就必需要修改對應的建立過程。然而IOC就沒有這個煩惱了,修改相應的配置就能夠了,代碼徹底不須要進行改動。
<bean id="gta5" class="com.hxh.service.impl.Gta5">
<constructor-arg name="username" value="不同的科技宅"></constructor-arg>
</bean>
複製代碼
IOC翻譯過來的意思是控制反轉,也被稱做爲依賴注入。經過將主動建立對象過程變成了被動接收,編譯期依賴變成了運行時依賴,以此來下降對象之間的耦合度。爲了實現依賴注入,須要在XML內配置好依賴關係,而且將對象實例化,銷燬,等過程統一交由IOC容器進行管理。這樣的話,因爲IOC容器將類的實例化過程透明化,而且建立的是單例對象,因此在方便調用方的使用同時,還減小了內存的佔用。
寫完心裏有點忐忑,若是有以爲寫的不對的地方,但願能在評論區指出來,感謝。
若是以爲對你有幫助,能夠多多評論,多多點贊哦,也能夠到個人主頁看看,說不定有你喜歡的文章,也能夠隨手點個關注哦,謝謝。