IoC 和 DI 都是 Spring 框架中的重要概念结笨,就像玫瑰花與愛情一樣包晰,IoC 和 DI 通常情況下也是成對(duì)出現(xiàn)的湿镀。那 IoC 和 DI 什么關(guān)系和區(qū)別呢?接下來伐憾,我們一起來看勉痴。
1.IoC 介紹
IoC 是 Inversion of Control 的縮寫,翻譯成中文是“控制反轉(zhuǎn)”的意思树肃,它不是一個(gè)具體的技術(shù)蒸矛,而是一個(gè)實(shí)現(xiàn)對(duì)象解耦的思想。
要解釋什么是解耦胸嘴?就要了解什么是耦合雏掠,所謂的耦合是指:兩個(gè)或兩個(gè)以上對(duì)象存在依賴,當(dāng)一方修改之后會(huì)影響另一方劣像,那么就說這些對(duì)象間存在耦合乡话。而解耦就是解除兩個(gè)或兩個(gè)以上對(duì)象,修改之后影響另一方的問題耳奕。
那 IoC(控制反轉(zhuǎn))是如何實(shí)現(xiàn)解耦的呢绑青?
我們來舉一個(gè)例子,比如 A 對(duì)象中需要使用 B 對(duì)象的某個(gè)方法吮铭,那么我們通常的實(shí)現(xiàn)方法是這樣的:
class A {
public void init() {
// 調(diào)用 B 類中的 init 方法
B b = new B();
b.init();
}
}
class B {
public B() {
}
public void init() {
System.out.println("你好时迫,世界。");
}
}
復(fù)制代碼
然而此時(shí)對(duì)象 A 和對(duì)象 B 是存在耦合的谓晌,因?yàn)橐坏┬薷牧?B 對(duì)象構(gòu)造方法的參數(shù)之后掠拳,那么 A 對(duì)象里面的寫法也要跟著改變,比如當(dāng)我們將構(gòu)造方法改為以下代碼時(shí):
class B {
public B(String name) {
System.out.println("姓名:" + name);
}
public void init() {
System.out.println("你好纸肉,世界溺欧。");
}
}
復(fù)制代碼
此時(shí)構(gòu)造方法已經(jīng)從原本無參構(gòu)造方法變成了有參的構(gòu)造方法,這里不考慮構(gòu)造方法重載的情況柏肪,因?yàn)閷?shí)際業(yè)務(wù)中姐刁,很可能是 B 類的構(gòu)造方法寫錯(cuò)了,忘記加參數(shù)了烦味,于是后面又補(bǔ)充了一個(gè)參數(shù)聂使,此時(shí)是不需要對(duì)構(gòu)造方法進(jìn)行重載的,那么此時(shí)谬俄,之前對(duì)象 A 里面的調(diào)用就會(huì)報(bào)錯(cuò)柏靶,如下圖所示:這就是開發(fā)中經(jīng)常遇到的一個(gè)問題,那怎么解決呢溃论?
我們可以通過將對(duì)象傳遞而并 new 對(duì)象的方式來解決屎蜓,如下代碼所示:
class A {
// 先定義一個(gè)需要依賴的 B 對(duì)象
private B b;
// 通過構(gòu)造方法實(shí)現(xiàn)賦值(初始化)
public A(B b) {
this.b = b;
}
public void init() {
// 調(diào)用 B 類中的 init 方法
b.init();
}
}
class B {
public B(String name) {
System.out.println("姓名:" + name);
}
public void init() {
System.out.println("你好,世界钥勋。");
}
}
復(fù)制代碼
這樣改造之后炬转,無論構(gòu)造方法怎么修改辆苔,即使需要加更多的參數(shù),而調(diào)用它的 A 類都無需做任何修改扼劈,這樣就實(shí)現(xiàn)了對(duì)象的解耦驻啤。
那這個(gè)解耦的示例和 IoC 有什么關(guān)系呢?
IoC 實(shí)現(xiàn)的思路和上述示例一樣测僵,就是通過將對(duì)象交給 Spring 中 IoC 容器管理街佑,在其他類中不直接 new 對(duì)象,而是通過將對(duì)象傳遞到當(dāng)前類的方式來實(shí)現(xiàn)解耦的捍靠。
小結(jié)
在 new 對(duì)象的時(shí)代沐旨,對(duì)象的管理權(quán)是由當(dāng)前類控制的,而有了 IoC 之后榨婆,對(duì)象的管理權(quán)就交給非當(dāng)前類的 IoC 容器管理了磁携,此時(shí)對(duì)象的管理權(quán)就發(fā)生了反轉(zhuǎn)和改變,這就是 IoC良风,這就是控制(權(quán))反轉(zhuǎn)谊迄。
2.DI 介紹
DI 是 Dependency Injection 的縮寫,翻譯成中文是“依賴注入”的意思烟央。依賴注入不是一種設(shè)計(jì)實(shí)現(xiàn)统诺,而是一種具體的技術(shù),它是在 IoC 容器運(yùn)行期間疑俭,動(dòng)態(tài)地將某個(gè)依賴對(duì)象注入到當(dāng)前對(duì)象的技術(shù)就叫做 DI(依賴注入)粮呢。
在上述示例中,A 類在使用 B 類時(shí)钞艇,就是通過構(gòu)造方法將依賴對(duì)象 B 引入的啄寡,這種實(shí)現(xiàn)方法就可以看作是通過構(gòu)造方法實(shí)現(xiàn)依賴注入的手段,具體代碼如下:
class A {
// 先定義一個(gè)需要依賴的 B 對(duì)象
private B b;
// 通過構(gòu)造方法實(shí)現(xiàn)賦值
public A(B b) {
this.b = b;
}
public void init() {
// 調(diào)用 B 類中的 init 方法
b.init();
}
}
復(fù)制代碼
3.IoC VS DI
從上面的內(nèi)容中我們可以看出哩照,IoC 和 DI 雖然定義不同挺物,但它們所做的事情都是一樣的,都是用來實(shí)現(xiàn)對(duì)象解耦的飘弧,而二者又有所不同:IoC 是一種設(shè)計(jì)思想识藤,而 DI 是一種具體的實(shí)現(xiàn)技術(shù)。
比如次伶,磊哥今天心情比較好蹋岩,想出去吃頓好的,那么“想吃頓好的”就是一種思想学少、就是 IoC。
但什么才是“好的(飯)”呢秧骑?海底撈還是韓式料理版确?具體吃什么是 DI扣囊。
因此“磊哥今天心情比較好,想出去吃頓好的”是一種思想绒疗、是 IoC侵歇,而吃一頓海底撈而非韓式料理就是具體的實(shí)現(xiàn)、是 DI吓蘑。
總結(jié)
IoC 和 DI 都是 Spring 框架中的重要概念惕虑,它們都是用來實(shí)現(xiàn)對(duì)象解耦的,其中 IoC(控制反轉(zhuǎn))是一種設(shè)計(jì)思想磨镶,而 DI(依賴注入)是一種具體的實(shí)現(xiàn)手段溃蔫。
作者:Java中文社群
鏈接:https://juejin.cn/post/7130040421731794974
來源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)琳猫,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處伟叛。