一、初識(shí) Spring
1.1 什么是 Spring
Spring 是一個(gè)開源的輕量級(jí) Java 框架,旨在簡(jiǎn)化 Java 應(yīng)用程序的開發(fā)。它提供了一個(gè)全面的編程和配置模型,用于構(gòu)建各種類型的應(yīng)用,包括企業(yè)級(jí)應(yīng)用和獨(dú)立的 Java 應(yīng)用。Spring 的設(shè)計(jì)理念是基于依賴注入(Dependency Injection)和面向切面編程(Aspect-Oriented Programming),使得應(yīng)用開發(fā)更加模塊化、靈活和易于維護(hù)。
用一句話概括 Spring 就是:Spring 是一個(gè)包含了眾多工具的 IoC 容器
。
1.2 什么是 容器
所謂容器就是能夠盛放東西的器皿,就好像水杯一樣。而 Spring 就是一個(gè)容器,它的功能就是負(fù)責(zé)存儲(chǔ)和管理應(yīng)用中的各個(gè)組件(Bean),然后在使用的時(shí)候從 Spring 中取出需要的 Bean 對(duì)象。
1.3 什么是 IoC
IoC,即控制反轉(zhuǎn)(Inversion of Control),是 Spring 框架的核心理念之一。它將應(yīng)用程序的控制權(quán)從開發(fā)人員的手中反轉(zhuǎn),由 Spring 容器負(fù)責(zé)管理對(duì)象的生命周期以及依賴關(guān)系。在傳統(tǒng)的程序設(shè)計(jì)中,開發(fā)人員需要負(fù)責(zé)手動(dòng)創(chuàng)建和管理對(duì)象,但是在 IoC 容器中,開發(fā)人員只需要定義組件(Bean)的配置元數(shù)據(jù),由容器負(fù)責(zé)實(shí)例化、裝配和管理這些組件。
二、對(duì) IoC 的深入理解
如果初次理解 IoC,可能會(huì)覺得很困難,可以通過(guò)下面的例子幫助我們理解 IoC 的作用。
假如,現(xiàn)在需要使用程序來(lái)模擬一個(gè)簡(jiǎn)單制造汽車的過(guò)程,其實(shí)現(xiàn)思路如下:
- 如果要造汽車Car,首先需要有車身Framework;
- 如果需要造車身Framework,首先就需要有地盤Bottom;
- 如果需要造地盤Bottom,首先就需要有輪子Tire。
上述過(guò)程,不難發(fā)現(xiàn)存在一個(gè)依賴鏈的關(guān)系,首先通過(guò)傳統(tǒng)程序的開發(fā)方式,來(lái)感受一下其存在的問(wèn)題。
2.1 傳統(tǒng)程序開發(fā)方式存在的問(wèn)題
下面是用傳統(tǒng)方式編寫的代碼:
class Tire {
private Integer size = 17;
public void init(){
System.out.println("do tire: size = " + size);
}
}
class Bottom {
private Tire tire;
public Bottom(){
this.tire = new Tire();
}
public void init(){
tire.init();
System.out.println("do bottom");
}
}
class Framework {
private Bottom bottom;
public Framework(){
bottom = new Bottom();
}
public void init(){
bottom.init();
System.out.println("do framework");
}
}
class Car {
private Framework framework;
public Car(){
framework = new Framework();
}
public void init(){
framework.init();
System.out.println("do car");
}
}
public class Tradition {
public static void main(String[] args) {
Car car = new Car();
car.init();
}
}
在上面的傳統(tǒng)寫法中,可以發(fā)現(xiàn)每個(gè)類之間的耦合度非常高,并且每個(gè)類都需要管理它所依賴的對(duì)象,即掌握著其依賴對(duì)象的控制權(quán)。此時(shí)如果用戶的需求改變了,使用的輪子Tire不再是固定的尺寸,而是需要由用戶自己輸入尺寸的大小,此時(shí)Tire類的代碼需要更改為:
class Tire {
private Integer size = 17;
public Tire(int size){
this.size = size;
}
public void init(){
System.out.println("do tire: size = " + size);
}
}
此時(shí)發(fā)現(xiàn),不改不要緊,但是一改問(wèn)題就來(lái)了,由于各個(gè)類之間的高耦合性,使得后續(xù)所依賴前者的代碼都需要進(jìn)行修改。
class Bottom {
private Tire tire;
public Bottom(int size){
this.tire = new Tire(size);
}
public void init(){
tire.init();
System.out.println("do bottom");
}
}
class Framework {
private Bottom bottom;
public Framework(int size){
bottom = new Bottom(size);
}
public void init(){
bottom.init();
System.out.println("do framework");
}
}
class Car {
private Framework framework;
public Car(int size){
framework = new Framework(size);
}
public void init(){
framework.init();
System.out.println("do car");
}
}
如果要后續(xù)要繼續(xù)增加 Tire 類的屬性,例如color,此時(shí)就還要需要從頭來(lái)進(jìn)行修改。那么如何解決這個(gè)缺陷呢?
上次代碼出現(xiàn)這個(gè)缺陷的根本原因就在于:當(dāng)前類將自己所依賴的類的控制權(quán)掌握在了自己的手中,即在自己類的內(nèi)部調(diào)用的所依賴類的構(gòu)造方法。因此解決這個(gè)問(wèn)題的方法也非常簡(jiǎn)單,那就是不在自己的內(nèi)部代碼中創(chuàng)建所依賴的對(duì)象,而是通過(guò)參數(shù)傳遞的方式獲取這個(gè)依賴對(duì)象,這就是控制權(quán)轉(zhuǎn)移的思想,即 IoC。
2.2 控制反轉(zhuǎn)式程序的開發(fā)
下面是轉(zhuǎn)移控制權(quán)的代碼寫法,即將當(dāng)前類所依賴的對(duì)象通過(guò)參數(shù)的方式進(jìn)行傳入:
class Tire {
private Integer size = 17;
public Tire(int size) {
this.size = size;
}
public void init() {
System.out.println("do tire: size = " + size);
}
}
class Bottom {
private Tire tire;
public Bottom(Tire tire) {
this.tire = tire;
}
public void init() {
tire.init();
System.out.println("do bottom");
}
}
class Framework {
private Bottom bottom;
public Framework(Bottom bottom) {
this.bottom = bottom;
}
public void init() {
bottom.init();
System.out.println("do framework");
}
}
class Car {
private Framework framework;
public Car(Framework framework) {
this.framework = framework;
}
public void init() {
framework.init();
System.out.println("do car");
}
}
public class IoC {
public static void main(String[] args) {
Tire tire = new Tire(18, "red");
Bottom bottom = new Bottom(tire);
Framework framework = new Framework(bottom);
Car car = new Car(framework);
car.init();
}
}
此時(shí),如果用戶需求又發(fā)生了改變,要求輪子 Tire 的顏色也要自己來(lái)挑選,此時(shí)更改的代碼如下:
class Tire {
private Integer size = 17;
private String color;
public Tire(int size, String color) {
this.size = size;
this.color = color;
}
public void init() {
System.out.println("do tire: size = " + size + ", color = " + color);
}
}
此時(shí),只需要修改 Tire 類和創(chuàng)建 Tire 對(duì)象的代碼,而不需要對(duì)其他代碼進(jìn)行修改??梢园l(fā)現(xiàn),即使底層類的改變也不會(huì)影響到整個(gè)調(diào)用鏈的改變,這樣就實(shí)現(xiàn)了代碼的解耦,從而實(shí)現(xiàn)了更加靈活、通用的程序設(shè)計(jì)方式。
2.3 對(duì)比總結(jié)
以下是傳統(tǒng)代碼和 IoC 形式代碼的調(diào)用過(guò)程:
通過(guò)對(duì)比兩種代碼的實(shí)現(xiàn)方式不難發(fā)現(xiàn):
-
兩種代碼中類的創(chuàng)建順序是相反的:
- 傳統(tǒng)代碼的創(chuàng)建順序是由頂層 Car 類創(chuàng)建到底層 Tire 類,即:
Car -> Framework -> Bottom -> Tire
; - 而 IoC 形式代碼的創(chuàng)建順序則是由底層 Tire 類創(chuàng)建到頂層 Car 類,即:
Tire -> Bottom -> Frame -> Car
。
- 傳統(tǒng)代碼的創(chuàng)建順序是由頂層 Car 類創(chuàng)建到底層 Tire 類,即:
- 傳統(tǒng)代碼中,當(dāng)前類掌握著自己所依賴對(duì)象的控制權(quán),耦合度非常高,一旦底層代碼修改了,整個(gè)調(diào)用鏈的代碼都會(huì)修改。
- IoC 形式的代碼中,當(dāng)前類通過(guò)參數(shù)傳遞的方式,將對(duì)所依賴對(duì)象的控制權(quán)進(jìn)行反轉(zhuǎn),即不再有自己掌控,此時(shí)無(wú)論底層代碼如何修改,也不會(huì)對(duì)整個(gè)調(diào)用鏈上的代碼造成影響。
三、對(duì) Spring IoC 的理解
“Spring 是一個(gè) 包含眾多工具的 IoC 容器” 這句話的理解非常重要,因?yàn)樗沂玖?Spring 框架最核心的功能和優(yōu)勢(shì)。在這里,我們可以把 Spring IoC 容器比喻成一個(gè)大大的容器,用來(lái)存放應(yīng)用程序中的各種對(duì)象(Bean)。這個(gè)容器不僅負(fù)責(zé)對(duì)象生命周期的管理,還實(shí)現(xiàn)了對(duì)象之間的依賴注入(DI),從而實(shí)現(xiàn)了控制反轉(zhuǎn)。
既然 Spring 是容器,那么它的核心功能就可以分為兩個(gè):
1. 將對(duì)象存入容器
- 程序員首先需要?jiǎng)?chuàng)建應(yīng)用程序中的各種對(duì)象(Bean),這些對(duì)象代表應(yīng)用程序中的不同組件和功能模塊。
- 然后通過(guò)配置文件(如XML、注解或者 Java 配置類)告訴 Spring IoC 容器如何創(chuàng)建這些對(duì)象,以及它們之間的依賴關(guān)系。
- Spring IoC 容器會(huì)根據(jù)配置信息,在應(yīng)用程序啟動(dòng)的時(shí)候負(fù)責(zé)實(shí)例化這些對(duì)象并存放到容器中,從而完成對(duì)象的創(chuàng)建和組裝過(guò)程。
2. 從容器中取出對(duì)象
- 一旦對(duì)象被存入了 Spring IoC 容器中,它們就可以在應(yīng)用程序的其他部分被獲取和使用。程序員不需要顯示地創(chuàng)建對(duì)象,而是從 Spring 容器中直接獲取已經(jīng)創(chuàng)建好的對(duì)象來(lái)使用。
- 通過(guò)依賴注入的方式,Spring IoC 容器會(huì)在合適的時(shí)候?qū)⒁蕾嚨膶?duì)象自動(dòng)注入到需要它們的地方。
總的來(lái)說(shuō),Spring IoC 容器負(fù)責(zé)管理對(duì)象的創(chuàng)建、組裝和依賴關(guān)系,開發(fā)人員只需關(guān)注對(duì)象的定義和配置。通過(guò)將對(duì)象存入容器并從容器中獲取對(duì)象,Spring 實(shí)現(xiàn)了對(duì)象的控制反轉(zhuǎn),使得應(yīng)用程序的開發(fā)更加簡(jiǎn)潔、靈活和易于維護(hù)。這也是 Spring 框架的核心之一,為開發(fā)者提供了一個(gè)強(qiáng)大且高度可定制的開發(fā)平臺(tái)。
四、DI 的概念
4.1 什么是 DI
依賴注入(Dependency Injection,DI)是一種實(shí)現(xiàn) IoC 的具體技術(shù),它是 IoC 容器的一種表現(xiàn)形式。在 DI 中,對(duì)象之間的依賴關(guān)系不再有類自己創(chuàng)建和管理,而是有外部容器(如 Spring)來(lái)負(fù)責(zé)注入依賴的對(duì)象。簡(jiǎn)單來(lái)說(shuō),DI 就是將一個(gè)對(duì)象的依賴關(guān)系交給外部容器來(lái)處理,從而實(shí)現(xiàn)對(duì)象之間的解耦。
在 DI 中,通常由三種注入方式:
- 構(gòu)造方法注入(Constructor Injection):通過(guò)構(gòu)造函數(shù)接收依賴對(duì)象,這是最常見的注入方式。
- Setter 方法注入(Setter Injection):通過(guò)Setter方法設(shè)置依賴對(duì)象。
- 屬性注入(Field Injection):通過(guò)屬性的方式注入依賴對(duì)象。
DI 使得對(duì)象的依賴關(guān)系從代碼中移出,變得可配置和靈活。通過(guò)使用DI,我們可以在應(yīng)用程序的不同部分之間實(shí)現(xiàn)松耦合,提高代碼的可測(cè)試性、可維護(hù)性和可擴(kuò)展性。
4.2 DI 與 IoC的關(guān)系
DI(依賴注入)和 IoC(控制反轉(zhuǎn))是緊密相關(guān)的概念,通常同時(shí)被提及,它們之間的關(guān)系可以概括為:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-631761.html
- IoC 是一種設(shè)計(jì)思想,它將應(yīng)用程序的控制權(quán)從代碼內(nèi)部轉(zhuǎn)移到外部容器。通過(guò) IoC,對(duì)象的創(chuàng)建和依賴關(guān)系的管理被反轉(zhuǎn),交由容器來(lái)負(fù)責(zé)管理,而不是由代碼顯示的控制。
- DI 是實(shí)現(xiàn) IoC 的一種具體技術(shù)手段,它是 IoC 的一種表現(xiàn)形式。通過(guò) DI,對(duì)象之間的依賴關(guān)系由外部容器來(lái)注入,而不是由對(duì)象自己來(lái)創(chuàng)建和管理依賴。
因此,DI 是 IoC 的一部分,它是實(shí)現(xiàn) IoC 的重要手段。Spring 框架正是以 IoC 和 DI 為核心,提供了強(qiáng)大的 IoC 容器和依賴注入機(jī)制,從而實(shí)現(xiàn)了各種功能,如依賴管理、AOP、事務(wù)管理等。通過(guò) IoC 和 DI,Spring 框架實(shí)現(xiàn)了松耦合、可配置和可擴(kuò)展的應(yīng)用程序開發(fā)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-631761.html
到了這里,關(guān)于【Spring】(一)Spring設(shè)計(jì)核心思想的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!