Spring是什么?

前言

前面我們學(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)思路是這樣的走净。

image.png

構(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ì)了味悄。

image.png

在傳統(tǒng)的代碼中對(duì)象創(chuàng)建順序是:Car -> Framework -> Bottom -> Tire

改進(jìn)之后解耦的代碼的對(duì)象創(chuàng)建順序是:Tire -> Bottom -> Framework -> Car

image.png

通用程序的實(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市榆骚,隨后出現(xiàn)的幾起案子片拍,更是在濱河造成了極大的恐慌,老刑警劉巖妓肢,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異苫纤,居然都是意外死亡碉钠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)卷拘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)喊废,“玉大人,你說(shuō)我怎么就攤上這事栗弟∥劭辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵乍赫,是天一觀的道長(zhǎng)瓣蛀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)雷厂,這世上最難降的妖魔是什么惋增? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮改鲫,結(jié)果婚禮上诈皿,老公的妹妹穿的比我還像新娘。我一直安慰自己像棘,他們只是感情好稽亏,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著缕题,像睡著了一般截歉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上避除,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天怎披,我揣著相機(jī)與錄音,去河邊找鬼瓶摆。 笑死凉逛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的群井。 我是一名探鬼主播状飞,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了诬辈?” 一聲冷哼從身側(cè)響起酵使,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎焙糟,沒(méi)想到半個(gè)月后口渔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡穿撮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年缺脉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悦穿。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡攻礼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出栗柒,到底是詐尸還是另有隱情礁扮,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布瞬沦,位于F島的核電站太伊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蛙埂。R本人自食惡果不足惜倦畅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绣的。 院中可真熱鬧叠赐,春花似錦、人聲如沸屡江。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惩嘉。三九已至罢洲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間文黎,已是汗流浹背惹苗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耸峭,地道東北人桩蓉。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像劳闹,于是被迫代替她去往敵國(guó)和親院究。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洽瞬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容