作者
:學Java的冬瓜
博客主頁
:?冬瓜的主頁🌙
專欄
:【Framework】
主要內容
:什么是spring?IoC容器是什么?如何使代碼解耦合?IoC的核心原理,IoC的優點。依賴注入/對象裝配/DI。
文章目錄
- 一、什么是Spring?
- 1)什么是IoC容器?
- 1> 理解
- 2> 法一,傳遞(存在依賴關系傳對象)
- 3> 法二,使用Spring
- Spring IoC 核心操作:
- Spring IoC 優點:
- 2)什么是DI?
一、什么是Spring?
Spring:包含了 眾多工具方法 的
IoC
容器。
1)什么是IoC容器?
1> 理解
IoC 全稱 Inversion of Control,翻譯為控制反轉。因此IoC容器就是控制反轉的容器。那啥是 控制反轉?Spring框架管理Bean的創建工作。即
由用戶管理Bean變為框架管理Bean
① 舉個例子:接下來我們舉個例子,并使用代碼來感受啥是個IoC(控制反轉),有什么好處:
比如建造一個房子,粗略的看,首先需要打地基,然后砌磚,最后掛房梁瓦片等。如果用代碼實現這樣一個粗略的過程,看下面代碼:
//測試類
public class Test {public static void main(String[] args) {House house = new House();house.init();}
}
//房
public class House {public void init(){// 創建房子 依賴于掛房梁等操作Beam beam = new Beam();beam.init();System.out.println("House: House create");}
}
//房梁
public class Beam {private String material;//(杉木)public void init(){// 掛房梁等 依賴于 砌好磚Brick brick = new Brick();brick.init();System.out.println("Bean: 房梁木用 " + this.material);}
}
//磚
public class Brick {private String redBrick;//紅磚public void init(){// 砌磚 依賴于 已經打好地基Foundation foundation = new Foundation();foundation.init();System.out.println("Brick: 砌磚用 " + this.redBrick);}
}
//地基
public class Foundation {private String rebar;//鋼筋private String cement;//水泥public void init(){System.out.println("Foundation: 打地基用 " + this.rebar +" "+ this.cement);}
}
上述代碼運行結果如下:
② 理解代碼:上面的代碼中,測試類中的main方法運行后,會創建一個空House對象,再進行House對象的初始化;在House對象初始化時,會創建一個空的Beam對象,然后進行beam對象的初始化(house依賴于beam,房子依賴于房梁);beam初始化時,會創建Brick對象,再進行brick對象的初始化(beam依賴于brick,房梁依賴于砌好磚);brick對象初始化時,會創建Foundation對象,并進行foundation對象的初始化。
簡單來說,要想建房子,得先掛好房梁,要想掛房梁,得先砌好磚,要想砌磚,得先打好地基,這就是一個逐層調用進行初始化的過程,最終建好一個房子。但是這樣操作會引入一個很致命的問題:代碼耦合度非常高!
③ 問題:這樣互相依賴的過程,如果底層的類發生改變,上層的類得相應改變。在上面代碼中,我使用鋼筋水泥打地基,用紅磚來砌磚,用杉木來做房梁木,在每個類的調用init方法時將所需參數傳進去,進行材料的初始化(我這里沒弄,所以都是null)。那么理解到這里我們可以想一個問題,如果我不再使用紅磚來砌磚,而是使用水泥磚了,或者我需要制定特定尺寸的磚,那么Brick類的屬性就需要修改調整。這樣在上層調用中(beam)也需要修改,在Beam類的init方法中,創建了Brick類,并使用brick.init(參數)這個方法進行砌磚的初始化,那么這里也是需要修改的,如果上層還有給brick傳參的方法,那也還需要改,所以這樣操作,代碼耦合度會非常高。
④ IoC和Spring:怎么才能降低耦合,減少修改的成本?因為上述代碼出現高耦合的原因:在當前類中的方法中,創建當前類所依賴的類的對象并逐層調用初始化對象,或者上層的代碼給底層的類的屬性傳參數。
法一:當存在依賴關系時,在當前類的方法中不再自己創建和銷毀所依賴的對象,而是讓調用者傳一個依賴對象給當前類(當前類需要一個成員變量是它所依賴的類),如果這個類還存在其他屬性,也由調用者提供參數(這樣就可保證,在我需要修改某一個類的成員或者類型時,其他類不需要做修改,即實現解耦合)。
法二:那如果我不讓它逐層調用,而是統一交給一個工具去創建對象并初始化并管理對象呢?這就是控制反轉,Spring就是管理對象的這樣一個容器。
⑤ Spring:在管理方面,Spring是一個 IoC容器,它可以管理對象,包括創建銷毀對象等。在操作方面,又因為是個 IoC容器,因此可以把對象存進Spring或者從Spring中獲取對象。
2> 法一,傳遞(存在依賴關系傳對象)
//測試類
package demo2;
public class Test {//測試傳對象 解耦合代碼public static void main(String[] args) {Foundation foundation = new Foundation("xx號鋼筋", "xx號水泥");Brick brick = new Brick(foundation, "xx號紅磚");Beam beam = new Beam(brick, "杉木");House house = new House(beam);house.init();}
}//House類
package demo2;
public class House {private Beam beam;public House(Beam beam){this.beam = beam;}public void init(){// 創建房子 依賴于掛房梁等操作beam.init();System.out.println("house: 房子建成");}
}//Beam類
package demo2;
public class Beam {private Brick brick;private String material;public Beam(Brick brick, String material){this.brick = brick;this.material = material;}public void init(){// 掛房梁等 依賴于 砌好磚brick.init();System.out.println("Bean: 房梁木用 " + this.material);}
}//Brick類
package demo2;
public class Brick {private Foundation foundation;private String redBrick;//紅磚public Brick(Foundation foundation, String redBrick){// 砌磚 依賴于 已經打好地基this.foundation = foundation;this.redBrick = redBrick;//新增}public void init(){this.foundation.init();System.out.println("Brick: 砌磚用 " + this.redBrick);}
}//Foundation類
package demo2;
public class Foundation {private String rebar;//鋼筋private String cement;//水泥public Foundation(String rebar, String cement){this.rebar = rebar;this.cement = cement;}public void init(){System.out.println("Foundation: 打地基用 " + this.rebar +" "+ this.cement);}
}
運行結果:
3> 法二,使用Spring
具體操作,看后面的博客
Spring IoC 核心操作:
存對象 取對象
Spring IoC 優點:
①
解耦合
②使用方便
(不再需要手動創建對象)
③更加高效
(默認情況,使用相同類只需要創建一個對象)
2)什么是DI?
IoC,(Inversion of Control 控制反轉)是一種設計原則,指的是將對象的創建和依賴關系交給容器來完成而不是由對象自己管理依賴對象。
DI,(Dependency Injection 依賴注入),是IoC的一種具體的實現方式,它是通過將依賴對象注入到對象中來實現對象之間的解耦。
簡而言之,IoC是一種思想,而DI是IoC的一種具體實現方式
。
補充1:實現IoC除了DI之外,還需要控制反轉容器(在Spring中就是Spring容器)和配置信息(xml文件,描述對象和依賴關系的元數據)。
補充2:① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩(在這里列出這種序號,需要的自取)。