什么是Spring?
Spring是一個開源的輕量級框架,是為了簡化企業級開發而設計的。我們通常講的Spring一般指的是Spring Framework。Spring的核心是控制反轉(IoC-Inversion of Control)和面向切面編程(AOP-Aspect-Oriented Programming)。這些功能使得開發者可以專注于業務邏輯的實現,不用去關注底層的實現。除此之外,Spring還可以與第三方庫和框架集成,如Mybatis等,使得我們開發更加方便。
我們來看看官方的解釋:
Spring | Why Spring
可以看到,spring包含了很多模塊,簡單來說:Spring是包含了很多工具方法的IoC容器。
什么是容器?
Spring容器是Spring框架中的核心組成部分,負責管理Spring Bean的生命周期和依賴關系,Spring容器是一個BeanFactory(Bean工廠),負責實例化、配置和管理Bean。
在Spring程序中,我們所有的Bean都是存放在容器中,通過IoC(控制反轉)技術進行管理。Spring容器通過自動裝配(autowiring)的方式將各個Bean之間建立聯系,從而減少手動配置的工作量。同時,Spring容器還提供了豐富的擴展機制,使得開發者可以根據自己的需求對bean進行定制化配置。
什么是IoC?
Spring IoC(控制反轉),是一種設計思想,通過將對象的創建和管理權交給了Spring容器,降低了程序之間的耦合性,
在Spring框架中,IoC主要通過XML配置文件、注解或Java配置等方式實現。通過使用IoC,應用程序的各個模塊之間就可以以低耦合的形式進行協同工作,提高應用程序的可擴展性和可維護性。
傳統程序開發流程
我們來舉個例子,來更好的理解上面所述內容。
假設我們現在要生產一輛車,其基本思路如下:
按照傳統的做法,我們生產一輛車,車的構成需要依賴車身(Framework),而車身需要依賴底盤(Bottom),底盤需要依賴輪胎(Tire)。
按照這種思路,我們用代碼實現如下:
public class CarProduct {public static void main(String[] args) {Car car = new Car();car.init();}/*** 汽車對象*/static class Car {private Framework framework;public Car() {framework = new Framework();}public void init() {framework.init();}}/*** 車身Framework*/static class Framework {private Bottom bottom;public Framework() {bottom = new Bottom();}public void init() {bottom.init();}}/*** 底盤Bottom*/static class Bottom {private Tire tire;public Bottom() {tire = new Tire();}public void init() {tire.init();}}/*** 輪胎Tire*/static class Tire {private int size = 20;//輪胎大小public void init() {System.out.println("輪胎大小:" + size);}}
}
我們可以看到,在上面的代碼中,輪胎的尺寸是固定的,但是現在車的數量非常多,車輪胎的尺寸不可能都是一樣的,所以我們就需要生產出各種尺寸大小的輪胎。我們需要對上面的代碼進行修改:
public class CarProduct {public static void main(String[] args) {Car car = new Car();car.init(10);}/*** 汽車對象*/static class Car {private Framework framework;public Car() {framework = new Framework();}public void init(int size) {framework.init(size);}}/*** 車身Framework*/static class Framework {private Bottom bottom;public Framework() {bottom = new Bottom();}public void init(int size) {bottom.init(size);}}/*** 底盤Bottom*/static class Bottom {private Tire tire;public Bottom() {tire = new Tire();}public void init(int size) {tire.init(size);}}/*** 輪胎Tire*/static class Tire {public void init(int size) {System.out.println("輪胎大小:" + size);}}
}
我們可以看到,雖然滿足我們的需求了,但是在上面的代碼中,不難看到,當最底層的代碼修改后,整個調用鏈上的代碼都需要進行修改,這樣耦合度就非常高了。
那么如果解決上面出現的這種問題呢?
在上面的代碼中,我們都是在每個類中創建下一個要調用的類,這樣的耦合度就非常高。
那么我們可以不在類中創建下級類,而是改為傳遞的方式(即注入),這樣我們就能實現解耦,下級類的改變發生變化,對于當前類來說,也無需修改任何代碼。
解耦指的是:解決了代碼之間的依賴程度,也可以叫做程序相關性,好的程序的代碼的耦合性是很低的,也就是代碼之間要解耦。
這就好比我們生產一輛汽車,如果所有的配件都是自己制造的,那么當客戶要改變需求時,如,客戶想要一個比較大的輪胎,那么我們就需要自己生產,這樣的效率是非常低的,但如果我們把輪胎的生產外包出去,那么就算輪胎的尺寸要發生改變,我們也能向代理公廠下單即可,無需自己生產,這樣效率就提高了不少。
控制反轉程序開發流程(IoC)
?根據上面所述,對代碼進行修改:
*** CarProduct類是汽車生產模型的示例,展示了如何通過組合不同類來構建復雜的對象結構*/
public class CarProduct {/*** 程序的入口點* 創建汽車對象及其組成部分,并初始化* @param args 命令行參數*/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.init();}/*** 汽車對象*/static class Car {private Framework framework;/*** 構造方法,初始化汽車的車身* @param framework 汽車的車身*/public Car(Framework framework) {this.framework = framework;}/*** 初始化汽車對象,包括其車身*/public void init() {framework.init();}}/*** 車身Framework*/static class Framework {private Bottom bottom;/*** 構造方法,初始化車身的底盤* @param bottom 車身的底盤*/public Framework(Bottom bottom) {this.bottom = bottom;}/*** 初始化車身對象,包括其底盤*/public void init() {bottom.init();}}/*** 底盤Bottom*/static class Bottom {private Tire tire;/*** 構造方法,初始化底盤的輪胎* @param tire 底盤的輪胎*/public Bottom(Tire tire) {this.tire = tire;}/*** 初始化底盤對象,包括其輪胎*/public void init() {tire.init();}}/*** 輪胎Tire*/static class Tire {private int size;//輪胎大小/*** 構造方法,初始化輪胎的大小* @param size 輪胎的大小*/public Tire(int size) {this.size = size;}/*** 初始化輪胎對象,打印輪胎大小*/public void init() {System.out.println("輪胎大小:" + size);}}
}
我們可以看到,通過上面的修改,就算底層類發生變化,整個調用鏈的代碼也是不用做任何修改的,這樣就實現代碼之間的解耦,從而提高了代碼的靈活性、復用性。
我們來對比一下傳統程序開發流程和控制反轉程序開發流程:
我們可以看到,傳統的開發流程是:Car依賴Framework,Framework依賴Bottom,...。而在改進之后的代碼中,控制權發生了反轉,不再是由上級對象創建下級對象并控制下級對象,而是下級對象注入到上級對象中,下級對象不再受上級對象的控制,這樣就算下級對象發生改變,也不會影響到上級對象,這就是典型的控制反轉,也就是IoC的實現思想。
?如何理解Spring IoC
在以往的程序設計中,對象之間的依賴關系通常是由程序內部通過new關鍵字來實現的,這樣的方式,會導致程序內部與具體實現的對象緊密聯系(即耦合度高),一旦對象的實現發生改變,那么對于程序中的一部分代碼也需要進行修改,這不僅增加了開發成本,而且也增加了代碼的維護難度。
Spring IoC則是將對象的創建和管理權交給了Spring容器。在Spring容器中,所有的對象稱為Bean,并通過配置文件或注解等方式來進行獲取對象。當程序某處需要用到Bean對象時,Spring容器就會負責查找、創建、注入Bean對象。而程序本身不需要關心Bean對象時如何實例化和管理的。這種方式的創建和管理權從原先的程序中轉移到Spring容器中,從而實現了控制反轉(IoC)。
Spring IoC的優點
- 降低耦合度:通過把對象的實例和管理權交給Spring容器,從而讓程序與對象之間的耦合性降低,使得代碼更加靈活、可維護、可復用。
- 提高可擴展性:由于對象的創建和管理權交給了Spring容器,當我們需要添加新的功能或模塊時,我們只需要在Spring中注冊相應的bean即可。
- 簡化開發:使用Spring IoC可以簡化開發。開發者只需要關注業務邏輯的實現,而不需要花費過多的精力在對象的創建和管理上。
- 提高性能:雖然使用Spring IoC會增加一些額外的開銷,但在大多數情況下,這種開銷是微不足道的。而且,通過使用Spring IoC,可以減少不必要的對象創建和銷毀,從而提高應用程序的性能。
DI(依賴注入)
DI(Dependcy Injection,即依賴注入)是一種軟件設計模式,用于實現松耦合和可測試性的代碼結構。在尋常的編程中,對象通常自己負責創建和管理它鎖依賴的其他對象,這樣導致了對象之間的耦合度高,使得對象難以復用和測試。
而DI是一種實現控制反轉(Inversion of Control,簡稱 IoC)的機制。它允許對象之間的依賴關系由外部容器(Spring 容器)來管理,而不是由對象自身來創建或查找依賴對象。這種方式可以減少對象之間的耦合性,提高代碼的可重用性和可維護性。
DI的實現方式
DI的主要實現方式包括構造函數注入、屬性注入和方法注入。
- 構造函數注入是最常見的DI方式,它通過在對象的構造函數中傳遞依賴對象來實現。
- 屬性注入是通過設置對象的屬性來注入依賴對象。
- 方法注入是一種更靈活的DI方式,它通過在對象的方法中傳遞依賴對象來實現。
DI的優點
- 降低耦合度:DI使得對象之間的耦合度降低,因為對象不直接創建依賴,而是通過外部注入的方式獲得。這使得每個對象更加獨立,更易于管理和維護。
- 提高代碼的可維護性:由于對象之間的耦合度降低,修改一個對象時對其他對象的影響也會減少,這使得代碼更易于維護和升級。
- 提高靈活性:DI使得對象的依賴關系可以動態地管理和修改,這使得代碼更加靈活,可以根據實際需求進行修改和擴展。
- 增強代碼的可測試性:依賴注入使得單元測試變得更加容易。開發者可以通過注入模擬(mock)對象或存根(stub)來測試組件的行為,而不需要依賴于實際的依賴對象。
- 提高代碼的可重用性:由于對象不依賴于具體的實現,而是依賴于抽象(接口或抽象類),因此可以更容易地替換對象的實現,從而提高代碼的可重用性。
Spring相關網站
Spring官方網站:Spring | Homehttps://spring.io/https://spring.io/https://spring.io/
Spring Framework官方文檔:Spring Framework 文檔 :: Spring Frameworkhttps://docs.spring.io/spring-framework/reference/https://docs.spring.io/spring-framework/reference/https://docs.spring.io/spring-framework/reference/
Spring Boot官方文檔:Spring Boot :: Spring Boothttps://docs.spring.io/spring-boot/index.htmlhttps://docs.spring.io/spring-boot/index.htmlhttps://docs.spring.io/spring-boot/index.html
Spring Cloud官方文檔:Spring Cloudhttps://spring.io/projects/spring-cloud#learnhttps://spring.io/projects/spring-cloud#learnhttps://spring.io/projects/spring-cloud#learn
Spring源代碼倉庫:Spring · GitHubhttps://github.com/spring-projectshttps://github.com/spring-projectshttps://github.com/spring-projects
Spring源代碼倉庫中文文檔:Spring Framework 中文文檔https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/
Spring Boot中文文檔:Spring Boot 參考https://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-startedhttps://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-startedhttps://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-started
Spring Cloud中文文檔:Spring Cloud 中文文檔https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/
以上就是本篇所有內容啦~
若有不足,歡迎指正~