前言
前面我們學(xué)習(xí)了 servlet 的相關(guān)知識(shí)想诅,但是呢?使用 servlet 進(jìn)行網(wǎng)站的開(kāi)發(fā)步驟還是比較麻煩的岛心,而我們本身程序員就屬于是比較懶的群體来破,所以為了解決咱們的這個(gè) servlet 步驟較為復(fù)雜的情況,一些大佬就在 servlet 的基礎(chǔ)上開(kāi)發(fā)出了 Spring 框架鹉梨,而 Spring 也因?yàn)槠漭p量和開(kāi)發(fā)效率高的特點(diǎn)讳癌,成為了 Java 圈子中非常受歡迎的一種框架。那么這篇文章我將為大家介紹一下什么是 Spring存皂。
什么是Spring
我們通常說(shuō)的 Spring 指的是 Spring FrameWork。Spring 是一個(gè)開(kāi)源的輕量級(jí)框架逢艘,它是為了簡(jiǎn)化企業(yè)級(jí)應(yīng)用開(kāi)發(fā)而設(shè)計(jì)的旦袋。Spring 提供了控制反轉(zhuǎn)(IOC)和面向切面編程(AOP)等核心功能,使得開(kāi)發(fā)者可以更加專(zhuān)注于業(yè)務(wù)邏輯的實(shí)現(xiàn)它改,而不需要關(guān)注底層的實(shí)現(xiàn)細(xì)節(jié)疤孕。Spring可以與各種第三方庫(kù)和框架集成,如Hibernate央拖、Struts等祭阀,使得這些庫(kù)和框架可以更加方便地在Spring應(yīng)用程序中使用鹉戚。此外,Spring還提供了一些模板類(lèi)专控,用于簡(jiǎn)化常見(jiàn)的開(kāi)發(fā)任務(wù)抹凳,如數(shù)據(jù)訪問(wèn)、事務(wù)管理等伦腐。
用一句話概括 Spring:Spring 是包含了眾多工具方法的 IoC 容器赢底。
那問(wèn)題來(lái)了,什么是容器柏蘑?什么是 IoC 容器幸冻?接下來(lái)我們一起來(lái)看。
什么是容器
Spring容器是Spring框架的核心組成部分咳焚,它負(fù)責(zé)管理Spring bean的生命周期和依賴關(guān)系洽损。Spring容器是一個(gè)bean工廠(BeanFactory),它負(fù)責(zé)實(shí)例化革半、配置和管理bean碑定。在Spring應(yīng)用程序中,所有的bean都存儲(chǔ)在Spring容器內(nèi)督惰,并通過(guò)IoC(控制反轉(zhuǎn))技術(shù)進(jìn)行管理不傅。Spring容器通過(guò)自動(dòng)裝配(autowiring)的方式將各個(gè)bean之間建立聯(lián)系,從而減少了手動(dòng)配置的工作量赏胚。同時(shí)访娶,Spring容器還提供了豐富的擴(kuò)展機(jī)制,使得開(kāi)發(fā)者可以根據(jù)自己的需求對(duì)bean進(jìn)行定制化配置觉阅。
什么是 IoC
Spring IoC即控制反轉(zhuǎn)(Inversion of Control)崖疤,是一種設(shè)計(jì)思想,它通過(guò)將對(duì)象的創(chuàng)建和管理權(quán)交給Spring容器典勇,降低了程序之間的耦合性劫哼,提高了系統(tǒng)的可維護(hù)性和可重用性。在Spring框架中割笙,IoC主要通過(guò)XML配置文件权烧、注解或Java配置等方式實(shí)現(xiàn)。通過(guò)使用IoC伤溉,應(yīng)用程序的各個(gè)模塊可以以松耦合的方式協(xié)同工作般码,提高了應(yīng)用程序的可擴(kuò)展性和可維護(hù)性。
傳統(tǒng)程序開(kāi)發(fā)
如何理解上面這段話呢乱顾?我們通過(guò)一個(gè)例子來(lái)解釋板祝。
假設(shè)我們現(xiàn)在構(gòu)建一輛車(chē)的程序,實(shí)現(xiàn)思路是這樣的走净。
構(gòu)建一輛車(chē)(Car Class)券时,然而車(chē)需要依賴車(chē)身(FrameWork Class)孤里,而車(chē)身需要依賴底盤(pán)(BottomClass),而底盤(pán)需要依賴輪胎(Tire Class)橘洞,最終程序的實(shí)現(xiàn)代碼如下:
public class NewCarExample {
public static void main(String[] args) {
Car car = new Car();
car.init();
}
/** * 汽車(chē)對(duì)象 */
static class Car {
public void init() {
// 依賴車(chē)身
Framework framework = new Framework();
framework.init();
}
}
/** * 車(chē)身類(lèi) */
static class Framework {
public void init() { // 依賴底盤(pán)
Bottom bottom = new Bottom();
bottom.init();
}
}
/** * 底盤(pán)類(lèi) */
static class Bottom {
public void init() { // 依賴輪胎
Tire tire = new Tire();
tire.init();
}
}
/** * 輪胎類(lèi) */
static class Tire { // 尺寸
private int size = 30;
public void init() {
System.out.println("輪胎尺寸:" + size);
}
}
}
以上程序中捌袜,輪胎的尺寸的固定的,然而隨著對(duì)的車(chē)的需求量越來(lái)越大震檩,個(gè)性化需求也會(huì)越來(lái)越多琢蛤,這時(shí)候我們就需要加工多種尺寸的輪胎,那這個(gè)時(shí)候就要對(duì)上面的程序進(jìn)行修改了抛虏,修改后的代碼如下所示:
public class NewCarUpdateExample {
public static void main(String[] args) {
Car car = new Car(20);
car.run();
}
/**
* 汽車(chē)對(duì)象
*/
static class Car {
private Framework framework;
public Car(int size) {
framework = new Framework(size);
}
public void run() {
// 依賴車(chē)身
framework.init();
}
}
/**
* 車(chē)身類(lèi)
*/
static class Framework {
private Bottom bottom;
public Framework(int size) {
bottom = new Bottom(size);
}
public void init() {
// 依賴底盤(pán)
bottom.init();
}
}
/**
* 底盤(pán)類(lèi)
*/
static class Bottom {
private Tire tire;
public Bottom(int size) {
tire = new Tire(size);
}
public void init() {
// 依賴輪胎
tire.init();
}
}
/**
* 輪胎類(lèi)
*/
static class Tire {
// 尺寸
private int size;
public Tire(int size) {
this.size = size;
}
public void init() {
System.out.println("輪胎尺寸:" + size);
}
}
}
從以上代碼可以看出博其,以上程序的問(wèn)題是:當(dāng)最底層代碼改動(dòng)之后,整個(gè)調(diào)用鏈上的所有代碼都需要修改迂猴。
那么如何解決這個(gè)問(wèn)題呢慕淡?
我們可以嘗試不在每個(gè)類(lèi)中自己創(chuàng)建下級(jí)類(lèi),如果自己創(chuàng)建下級(jí)類(lèi)就會(huì)出現(xiàn)當(dāng)下級(jí)類(lèi)發(fā)生改變操作沸毁,自己也要跟著修改峰髓。
此時(shí),我們只需要將原來(lái)由自己創(chuàng)建的下級(jí)類(lèi)息尺,改為傳遞的方式(也就是注入的方式)携兵,因?yàn)槲覀儾恍枰诋?dāng)前類(lèi)中創(chuàng)建下級(jí)類(lèi)了,所以下級(jí)類(lèi)即使發(fā)生變化(創(chuàng)建或減少參數(shù))搂誉,當(dāng)前類(lèi)本身也無(wú)需修改任何代碼徐紧,這樣就完成了程序的解耦。
解耦指的是解決了代碼的耦合性炭懊,耦合性也可以換一種叫法叫程序相關(guān)性并级。好的程序代碼的耦合性(代碼之間的相關(guān)性)是很低的,也就是代碼之間要實(shí)現(xiàn)解耦侮腹。
這就好比我們打造一輛完整的汽車(chē)嘲碧,如果所有的配件都是自己造,那么當(dāng)客戶需求發(fā)生改變的時(shí)候父阻,比如輪胎的尺寸不再是原來(lái)的尺寸了愈涩,那我們要自己動(dòng)手來(lái)改了,但如果我們是把輪胎外包出去加矛,那么即使是輪胎的尺寸發(fā)生變變了钠署,我們只需要向代理工廠下訂單就行了,我們自身是不需要出力的荒椭。
控制反轉(zhuǎn)式程序開(kāi)發(fā)
我們把調(diào)用汽車(chē)的
public class IocCarExample {
public static void main(String[] args) {
Tire tire = new Tire(20);
Bottom bottom = new Bottom(tire);
Framework framework = new Framework(bottom);
Car car = new Car(framework);
car.run();
}
static class Car {
private Framework framework;
public Car(Framework framework) {
this.framework = framework;
}
public void run() {
framework.init();
}
}
static class Framework {
private Bottom bottom;
public Framework(Bottom bottom) {
this.bottom = bottom;
}
public void init() {
bottom.init();
}
}
static class Bottom {
private Tire tire;
public Bottom(Tire tire) {
this.tire = tire;
}
public void init() {
tire.init();
}
}
static class Tire {
private int size;
public Tire(int size) {
this.size = size;
}
public void init() {
System.out.println("輪胎:" + size);
}
}
}
代碼經(jīng)過(guò)以上調(diào)整,無(wú)論底層類(lèi)如何變化舰蟆,整個(gè)調(diào)用鏈?zhǔn)遣挥米鋈魏胃淖兊娜せ荩@樣就完成了代碼之間的解耦狸棍,從而實(shí)現(xiàn)了更加靈活、通用的程序設(shè)計(jì)了味悄。
在傳統(tǒng)的代碼中對(duì)象創(chuàng)建順序是:Car -> Framework -> Bottom -> Tire
改進(jìn)之后解耦的代碼的對(duì)象創(chuàng)建順序是:Tire -> Bottom -> Framework -> Car
通用程序的實(shí)現(xiàn)代碼草戈,類(lèi)的創(chuàng)建順序是反的,傳統(tǒng)代碼是 Car 控制并創(chuàng)建了
Framework侍瑟,F(xiàn)ramework 創(chuàng)建并創(chuàng)建了 Bottom唐片,依次往下,而改進(jìn)之后的控制權(quán)發(fā)生的反轉(zhuǎn)涨颜,不再是上級(jí)對(duì)象創(chuàng)建并控制下級(jí)對(duì)象了费韭,而是下級(jí)對(duì)象把注入將當(dāng)前對(duì)象中,下級(jí)的控制權(quán)不再由上級(jí)類(lèi)控制了庭瑰,這樣即使下級(jí)類(lèi)發(fā)生任何改變星持,當(dāng)前類(lèi)都是不受影響的,這就是典型的控制反轉(zhuǎn)弹灭,也就是 IoC 的實(shí)現(xiàn)思想督暂。
理解Spring IoC
在傳統(tǒng)的程序設(shè)計(jì)中,對(duì)象之間的依賴關(guān)系通常是由程序內(nèi)部通過(guò)new關(guān)鍵字創(chuàng)建對(duì)象來(lái)實(shí)現(xiàn)的穷吮。這種方式會(huì)導(dǎo)致程序內(nèi)部與具體的對(duì)象實(shí)現(xiàn)緊密耦合逻翁,一旦對(duì)象實(shí)現(xiàn)發(fā)生改變,程序其他部分的代碼也需要相應(yīng)地進(jìn)行修改捡鱼。這不僅增加了開(kāi)發(fā)成本八回,也增加了代碼的維護(hù)難度。
而Spring IoC則將對(duì)象的創(chuàng)建和管理權(quán)交給了Spring容器堰汉。在Spring容器中辽社,所有的對(duì)象都被稱(chēng)為bean,并通過(guò)配置文件或注解等方式進(jìn)行注冊(cè)翘鸭。當(dāng)程序需要使用某個(gè)bean時(shí)滴铅,Spring容器會(huì)負(fù)責(zé)查找和注入該bean,而程序本身并不需要關(guān)心具體的bean實(shí)例化和管理就乓。這種方式將對(duì)象的創(chuàng)建和管理權(quán)從程序轉(zhuǎn)移到了Spring容器汉匙,從而實(shí)現(xiàn)了控制反轉(zhuǎn)。
控制反轉(zhuǎn)的好處在于:
降低耦合性:通過(guò)將對(duì)象的創(chuàng)建和管理權(quán)交給Spring容器生蚁,程序與其他對(duì)象之間的耦合性降低噩翠,使得程序更加靈活、可維護(hù)和可重用邦投。
提高可擴(kuò)展性:由于對(duì)象的創(chuàng)建和管理權(quán)交給了Spring容器伤锚,當(dāng)需要添加新的功能或模塊時(shí),只需要在Spring容器中注冊(cè)相應(yīng)的bean即可志衣。這使得應(yīng)用程序可以更加方便地進(jìn)行擴(kuò)展和升級(jí)屯援。
簡(jiǎn)化開(kāi)發(fā):使用Spring IoC可以簡(jiǎn)化開(kāi)發(fā)過(guò)程猛们。開(kāi)發(fā)者只需要關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn),而不需要花費(fèi)過(guò)多的精力在對(duì)象的創(chuàng)建和管理上狞洋。
提高性能:雖然使用Spring IoC會(huì)增加一些額外的開(kāi)銷(xiāo)弯淘,但在大多數(shù)情況下,這種開(kāi)銷(xiāo)是微不足道的吉懊。而且庐橙,通過(guò)使用Spring IoC,可以減少不必要的對(duì)象創(chuàng)建和銷(xiāo)毀借嗽,從而提高應(yīng)用程序的性能态鳖。
DI
說(shuō)到 IoC 不得不提的一個(gè)詞就是“DI”,DI 是 Dependency Injection 的縮寫(xiě)淹魄,翻譯成中文是“依賴注入”的意思郁惜。
DI(Dependency Injection)是一種軟件設(shè)計(jì)模式,它用于實(shí)現(xiàn)松耦合和可測(cè)試性的代碼結(jié)構(gòu)甲锡。在常規(guī)的編程模式中兆蕉,對(duì)象通常自己負(fù)責(zé)創(chuàng)建和管理它所依賴的其他對(duì)象,這導(dǎo)致了高度的依賴性缤沦,使得對(duì)象難以重用和測(cè)試虎韵。而DI通過(guò)將對(duì)象的依賴關(guān)系交給外部系統(tǒng)來(lái)管理,以解耦對(duì)象之間的關(guān)系缸废,并提供了更高的靈活性和可測(cè)試性包蓝。
DI的主要實(shí)現(xiàn)方式包括構(gòu)造函數(shù)注入、屬性注入和方法注入企量。構(gòu)造函數(shù)注入是最常見(jiàn)的DI方式测萎,它通過(guò)在對(duì)象的構(gòu)造函數(shù)中傳遞依賴對(duì)象來(lái)實(shí)現(xiàn)。屬性注入是通過(guò)設(shè)置對(duì)象的屬性來(lái)注入依賴對(duì)象届巩。方法注入是一種更靈活的DI方式硅瞧,它通過(guò)在對(duì)象的方法中傳遞依賴對(duì)象來(lái)實(shí)現(xiàn)。
DI的好處包括:
降低耦合性:通過(guò)將對(duì)象的依賴關(guān)系交給外部系統(tǒng)來(lái)管理恕汇,DI使得對(duì)象之間的關(guān)系更加松散腕唧,提高了代碼的可維護(hù)性和可重用性。
提高可測(cè)試性:DI使得對(duì)象的依賴關(guān)系可以通過(guò)外部系統(tǒng)進(jìn)行配置和管理瘾英,這使得單元測(cè)試更加容易枣接,提高了代碼的可測(cè)試性。
提高靈活性:DI使得對(duì)象之間的依賴關(guān)系可以動(dòng)態(tài)地改變和管理缺谴,這使得代碼更加靈活但惶,可以根據(jù)實(shí)際需求進(jìn)行定制和擴(kuò)展。
https://developer.aliyun.com/article/1430658?spm=a2c6h.12873639.article-detail.16.5ef74f88Ooq3aS&scm=20140722.ID_community
Spring幫助網(wǎng)站
Spring官方網(wǎng)站:https://spring.io/
Spring Framework官方文檔:https://docs.spring.io/spring-framework/docs/current/reference/html/
Spring Boot官方文檔:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/
Spring Cloud官方文檔:https://spring.io/projects/spring-cloud#learn
Spring社區(qū)論壇:https://community.spring.io/
Spring源代碼倉(cāng)庫(kù):https://github.com/spring-projects/spring-framework
Spring源代碼倉(cāng)庫(kù)中文文檔:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/
Spring Boot中文文檔:https://www.docs4dev.com/docs/zh/spring-boot/2.1.3.RELEASE/reference/
Spring Cloud中文文檔:https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/
Spring官方博客:https://spring.io/blog