什麼是 Spring?為什麼學它?

2023-05-24 06:00:54

前言

歡迎來到本篇文章!在這裡,我將帶領大家快速學習 Spring 的基本概念,並解答兩個關鍵問題:什麼是 Spring,以及為什麼學習 Spring。

廢話少說,下面,我們開始吧!

Spring 官方檔案:https://docs.spring.io/spring-framework/docs/5.2.24.RELEASE/spring-framework-reference/

為什麼需要學習 Spring?

  1. 簡化我們的企業級應用程式的開發,提升我們的開發效率。
  2. 學 Java 的路上不得不學 Spring,不學直接用 Spring Boot 是可以,開箱即用,但是很難學懂,可能只是會用,不能知其然而知其所以然。
  3. 面試會問的啊!工作會用的啊!所以需要學嘛!OK!

Spring 這個詞,指的是什麼?

Spring 這個術語在不同的上下文中有不同的含義。它可以用來指代 Spring Framework 專案本身,這是夢開始的地方。

後來隨著時間的推移,其他基於 Spring Framework 構建的專案也相繼出現。當人們說 Spring 時,通常指整個專案家族。不過,在本系列中,我們就只指代它本身,即 Spring Framework 本身。

Spring Framework 被分為多個模組,應用程式可以選擇需要哪些模組。核心容器模組包括設定模型和依賴注入機制等內容。除此之外,Spring Framework 還為不同型別應用架構提供了基礎支援,包括訊息傳遞、事務資料和持久化以及 Web 開發等領域,並且同時提供了基於 ServletSpring MVC Web 框架和並行執行的 Spring WebFlux 響應式 Web 框架。

Spring 的模組

實際上,Spring Framework 大約由 20 個模組組成。這些模組分為核心容器、資料存取/整合、Web、AOP(面向切面程式設計)、儀表板、訊息和測試等。如官網上給出的這張圖所示:

Core Container(核心模組)

當我們談論 Spring 的核心容器時,我們指的是一些模組,它們共同構成了這個框架的基礎。這些模組包括 spring-corespring-beansspring-contextspring-context-supportspring-expression

首先,讓我們來了解一下 spring-corespring-beans 模組。它們提供了一些基本功能,其中最重要的是「IoC(控制反轉)」和「依賴注入」。簡單來說,IoC 允許我們將物件的建立和管理交給框架來處理,而不是我們自己手動建立和管理。依賴注入則是一種將物件之間的依賴關係注入到它們之間的過程,這樣可以實現物件之間的解耦。

另外,BeanFactory 是一個工廠模式的複雜實現,它的作用是消除編寫單例模式的需要,並且允許我們將物件的設定和規範與實際的程式邏輯分離開來。

接下來是 Contextspring-context)模組,它是在 CoreBeans 模組的基礎上構建的。Context 模組提供了一種類似於 JNDI(Java命名和目錄介面)登入檔的方式來存取物件。除了繼承 Beans 模組的功能外,Context 模組還新增了對國際化、事件傳播、資源載入等功能的支援。它還能夠通過 Servlet 容器等方式透明地建立上下文。此外,Context 模組還支援一些 Java EE 特性,如 EJB(企業級 Java Bean)、JMX(Java管理擴充套件)和基本的遠端處理。在 Context 模組中,ApplicationContext 介面是重點關注的物件。另外,spring-context-support 模組為將常見的第三方庫整合到 Spring 應用程式上下文中提供了支援,尤其是在快取(EhCache、JCache)和排程(CommonJ、Quartz)方面。

最後,我們有 spring-expression 模組,它提供了一個強大而靈活的表示式語言,用於在執行時查詢和操作物件圖(object graph)。該語言是 JSP 2.1 規範中統一表示式語言(unified EL)的擴充套件。它支援設定和獲取屬性值、屬性賦值、方法呼叫、存取陣列、集合和索引器的內容,以及邏輯和算術運運算元、命名變數等。通過 Spring IoC 容器,我們還可以按名稱檢索物件。此外,該表示式語言還支援列表投影、選擇和常見的列表聚合操作。

AOP 和 Instrumentation

spring-aop 模組是 Spring 框架中用於實現面向切面程式設計的一部分,它遵循 AOP Alliance 標準。

那麼什麼是面向切面程式設計呢?簡單來說,它允許我們在程式碼中定義方法的攔截器和切入點,從而將某些功能與實際業務邏輯分離開來,以實現更清晰的程式碼結構和更好的模組化。舉個例子,比如當我們需要在程式碼中引入一些紀錄檔記錄、安全性檢查、效能監控的程式碼,那麼這些程式碼就是橫切關注點,我們可以使用 AOP 來實現這些程式碼的引入,而不是將這些程式碼分散到各個業務邏輯中。通過使用 AOP,我們可以將這些通用的橫切關注點定義為切面,並將它們應用到適當的方法上,從而實現程式碼的解耦和重用。

此外,Spring 還提供了單獨的 spring-aspects 模組,用於與 AspectJ 進行整合。AspectJ 是一個功能強大的 AOP 框架,通過與 Spring 的整合,我們可以利用 AspectJ 的更高階功能來實現更復雜的切面程式設計。

另外還有一個模組叫做 spring-instrument,它提供了類儀表化(instrumentation)的支援和類載入器實現,在某些應用伺服器中可以使用。這個模組的作用是提供一些工具和機制,以便在執行時對類進行修改和增強,從而實現一些特定的需求。例如,spring-instrument-tomcat 模組是針對 Tomcat 伺服器的特定實現,它提供了用於儀表化的代理機制。

Messaging

Spring 4 引入了一個名為 spring-messaging 的模組,它包含了 Spring Integration 專案的核心抽象,例如 MessageMessageChannelMessageHandler 等等。這個模組的目的是提供訊息傳遞應用程式的基礎支援。

通過 spring-messaging 模組,我們可以構建基於訊息傳遞的應用程式,其中不同元件之間通過訊息進行通訊。以下是一些關鍵概念和功能:

  1. Message訊息是應用程式中傳遞的資料單元。它可以包含有關訊息內容和後設資料的資訊。
  2. MessageChannel訊息通道是訊息在應用程式中傳遞的路徑。它充當傳送者和接收者之間的中介。
  3. MessageHandler訊息處理器是負責接收和處理訊息的元件。它可以執行特定的業務邏輯或轉發訊息給其他元件。

spring-messaging 模組還引入了一組註解,用於將訊息對映到方法,類似於 Spring MVC 中基於註解的程式設計模型。這使得我們可以通過簡單的註解來定義訊息的處理方式,讓程式碼更加清晰和易於理解。

Data Access/Integration

當我們處理資料時,Spring 的資料存取/整合層提供了一些模組,以幫助我們更輕鬆地與資料庫和其他資料來源進行互動。

  • spring-jdbc 模組簡化了與資料庫進行互動的過程。它提供了一個抽象層,讓我們可以使用更簡單、更易於理解的程式碼來執行資料庫操作,而不必處理繁瑣的細節。
  • spring-tx 模組支援事務管理。事務是用來確保資料的一致性和完整性的機制。使用 Spring 的事務管理模組,我們可以以程式設計式或宣告式的方式來管理事務,從而更輕鬆地處理資料的變化和操作。
  • spring-orm 模組提供了與物件關係對映(ORM)框架的整合。ORM 是一種將資料庫中的資料對映到物件的技術,它使得我們可以使用物件導向的方式來運算元據庫。通過使用 Spring 的 ORM 模組,我們可以方便地整合流行的 ORM 框架(如 Hibernate、MyBaits),並結合 Spring 的其他功能,例如簡單的宣告式事務管理。
  • spring-oxm 模組提供了物件和 XML 之間的對映支援。它可以幫助我們將 Java 物件轉換成 XML 格式,或者將 XML 轉換回 Java 物件。這對於處理與 XML 相關的資料非常有用。
  • spring-jms 模組用於處理 Java 訊息服務(Java Message Service)。它提供了生成和消費訊息的功能。從 Spring Framework 4.1 版本開始,它還與 spring-messaging 模組進行了整合,使得基於訊息傳遞的應用程式開發更加方便。

Web

Web 層由 spring-webspring-webmvc 等模組組成。

  • spring-web 模組提供了基本的 Web 功能。它包含處理 MultipartFile 上傳使用 Servlet 監聽器進行初始化 IoC 容器的功能。該模組還包含與Web相關的部分,如 HTTP 使用者端Spring 遠端支援,以便與其他Web服務進行通訊。
  • spring-webmvc 模組(也稱為Web-Servlet模組)是 Spring 框架中用於構建 Web 應用程式的重要模組。它實現了 Model-View-Controller(MVC)架構和 RESTful Web 服務。使用 Spring MVC,我們可以將業務邏輯程式碼和 Web 表單清晰地分離,實現更好的程式碼組織和可維護性。該模組與 Spring 的其他功能無縫整合,使我們能夠輕鬆地使用依賴注入、事務管理等功能來構建靈活和可延伸的Web應用程式。

Test

spring-test 模組支援使用 JUnit 或 TestNG 對 Spring 元件進行單元測試和整合測試,它提供了一致的 Spring ApplicationContext 載入和快取機制,並提供了 Mock 物件,便於我們進行測試。

Spring 的歷史

Spring 框架於 2003 年誕生,是對早期 J2EE 規範複雜性的迴應。雖然有些人認為 Java EE 和 Spring 存在競爭關係,但實際上,Spring 與 Java EE 相輔相成。Spring 程式設計模型並不包含 Java EE 平臺規範;相反,它整合了來自 EE 大傘下精心挑選的個別規範:

  • Servlet API(JSR 340)

  • WebSocket API(JSR 356)

  • Concurrency Utilities(JSR 236)

  • JSON Binding API(JSR 367)

  • Bean Validation(JSR 303)

  • JPA(JSR 338)

  • JMS (JSR914),以及必要時用於事務協調的 JTA/JCA 設定。

Spring 框架還支援依賴注入(JSR330)和常見註解(JSR250)規範,我們開發人員可以選擇使用這些規範而非由 Spring 框架提供的特定機制。

從 Spring Framework 5.0 開始,Spring 要求 Java EE 7 級別(例如 Servlet 3.1+,JPA 2.1+)作為最低要求,同時在執行時提供與 Java EE 8 級別的新API(例如 Servlet 4.0、JSON Binding API)的開箱即用整合。這使得 Spring 完全相容 Tomcat 8 和 9、WebSphere 9 以及 JBoss EAP 7 等伺服器。

隨著時間推移,在應用程式開發中 Java EE 的角色也在不斷演變。在 Java EE 和 Spring 的早期,應用程式是為部署到應用伺服器而建立的。如今,在 Spring Boot 的幫助下,應用程式以 devops 和雲友好的方式建立,Servlet 容器被嵌入其中並且易於更改。從 Spring Framework5 開始,WebFlux 應用程式甚至不直接使用 Servlet API,並且可以執行在非 Servlet 容器(例如 Netty )上。

Spring 繼續創新和發展。除了 Spring Framework 之外,還有其他專案,例如 Spring Boot、Spring Security、Spring Data、Spring Cloud、Spring Batch 等等。

Spring 設計理念

當你學習一個框架時,瞭解它所做的事情以及遵循的原則同樣重要。以下是 Spring Framework 的指導原則:

  • 在每個層面提供選擇:Spring 允許我們儘可能地推遲設計決策。例如,我們可以通過設定切換應用程式所連線的資料庫而無需更改程式碼。對於許多其他基礎設施問題和第三方API的整合也是如此。

  • 容納不同的觀點:Spring 非常靈活,沒有固定的方式來解決應用程式的需求。它提供了多種方法來完成相同的任務,以適應不同開發者的不同觀點和需求。

  • 保持強大的向後相容性:Spring Framework 的設計經過精心考慮,儘量減少對你已有程式碼的影響。這意味著當我們升級到新的版本時,我們的應用程式仍然可以正常執行,而無需擔心因為框架更新而導致問題。Spring 還支援多個 Java 開發工具包(JDK)版本和第三方庫,這樣你可以繼續使用 Spring 來開發和維護你的應用程式。

  • 關注 API 設計:Spring 團隊花費了大量的時間和精力來設計直觀易懂、穩定可靠的 API。他們努力確保 API 在多個版本和多年的時間跨度中保持一致性,這樣我們就可以更輕鬆地理解和使用它們。

  • 確立高標準程式碼質量:Spring Framework 強調清晰、準確的檔案註釋。它是少數幾個程式碼結構清晰且包之間沒有迴圈依賴關係的專案之一。這種高標準的程式碼質量有助於提高框架的可維護性和可延伸性。

所以什麼是 Spring?

Spring 是一個輕量級的、開源的 Java 框架,實現了 IoC(Inversion of Control)和 AOP(Aspect Oriented Programming)等功能。

在 Spring 的官網介紹中,Spring 被描述為「構建企業級應用程式的一站式框架」,它提供瞭如下的優點:

  • 便於開發:Spring 的元件化和鬆耦合的特性使得開發變得更加簡單,開發者可以更加專注於業務邏輯的實現。
  • 便於測試:Spring 的程式碼結構和依賴注入機制使得測試變得更加容易。
  • 便於整合:Spring 的可插拔的架構,使得其可以方便地與其他框架和元件進行整合。
  • 便於部署:Spring 應用程式的部署非常簡單,開發者只需要將應用程式打成 war 包,然後將其部署到支援 Java 應用程式的伺服器上即可。

Spring 框架包含了如下的模組:

  • 核心容器(Core Container):包括 IoC 和 DI(Dependency Injection,依賴注入)、事件、資源、國際化、驗證、資料繫結、型別轉換、SpEL 和 AOP 等核心功能。
  • AOP:支援面向切面程式設計。
  • 工具(Instrumentation):提供了一系列的工具和支援,如 JMS、JCA、JMX、電子郵件、任務排程和快取等。
  • 資料存取/整合(Data Access/Integration):包括對 JDBC、ORM 框架(如 Hibernate、MyBatis)事務處理,DAO 等的支援。
  • Web:包括對 Web 應用程式開發的支援,如 Spring MVC 和 Spring WebFlux 網路框架等。
  • 測試(Test):包括對 JUnit、TestNG 等的支援。

沒有 Spring 和有 Spring 的區別

那到底是怎樣簡化了呢?體現在哪裡呢?下面,為了直觀展示 Spring 是如何簡化我們開發的過程的,將寫一個程式碼範例,讓大家看看是怎樣的區別。

物件管理

當沒有 Spring 時,Java EE 開發的主要方式是使用 JSP、Servlet 和 EJB 等技術。你想一想,剛開始學習 JSP 的時候,是不是這樣,沒有任何框架,純純自己操作所有東西。

對於系統中多個物件之間的關係,沒有 Spring 的時候,我們需要手動建立和管理物件之間的依賴關係

這句話可能初學者不是很好理解,我舉個例子。

這裡有兩個設計好的系統中的兩個類,Employee 和 Department(用於描述員工以及部門資訊的類)。

Employee.java:

public class Employee {
    private int id;
    private String name;
    private Department department;
    
    // 省略 getter 和 setter
}

Department.java:

public class Department {
    private int id;
    private String name;
    
    // 省略 getter 和 setter
}

未使用 Spring 的時候

我們現在的業務假設是需要列印員工的部門資訊,那麼我們就需要手動管理它們之間的依賴關係的,程式碼如下:

public class Main {
    public static void main(String[] args) {
        Department department = new Department(1, "Just do IT");
        Employee employee = new Employee(1, "god23bin", department);
        System.out.println(employee.getDepartment().getName());
    }
}

你建立一個 Employee 物件,就必須自己再去建立一個 Department 物件(因為 Employee 物件依賴於 Department 物件),並將 Department 物件給關聯到 Employee 物件上。是吧。現在,我相信螢幕前的你已經懂了所謂的手動建立和管理物件之間的依賴關係了。

使用 Spring 的時候

當你使用 Spring 的時候,就完全不需要這麼做。依然是這個例子,現在我使用 Spring 來操作,物件的管理就交給 Spring 處理,來看看我怎麼寫的:

@Configuration
public class AppConfig {
    
    @Bean
    public Department department() {
        return new Department(1, "Just do IT");
    }
    
    @Bean
    public Employee employee() {
        return new Employee(1, "god23bin", department());
    }
    
}

我寫了一個 AppConfig 類,在類上使用了一個 @Configuration 註解,表示這是一個設定類。

接著,寫了兩個方法,分別返回了一個員工物件和一個部門物件,而且在方法上使用了一個 @Bean 註解,表示這個方法返回的物件是交給 Spring IoC 進行管理的。

這兩個物件都是通過呼叫構造方法來建立的,其中 Department 物件則被注入到了 Employee 物件中。(注入,你就理解成 setXxx 方法)

在最上面進行介紹的時候,有一個概念,就是「容器」,這個容器人們也習慣稱「Ioc 容器」,實際上就是 Spring 用來存放與管理應用程式中所有交給它的物件的。

現在在這個容器中,就有 Department 物件和 Employee 物件。

我們的業務依舊是列印員工的部門資訊,此刻,我們只需要從「容器」中獲取我們需要的物件就可以了,直接獲取員工物件,不用手動自己 new 一個員工物件,也不需要自己 new 一個部門物件了。

我們通過 AnnotationConfigApplicationContext 來載入設定類 AppConfig,然後通過 getBean 方法來獲取 Employee 物件,此過程 Spring 完成了依賴注入的效果,Employee 物件是具有 Department 物件的。

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Employee employee = context.getBean(Employee.class);
        System.out.println(employee.getDepartment().getName());
    }
}

不過,實際上,我們在真正的專案中,並不會這樣去使用,即不會去手動寫 context.getBean() 等這些程式碼,而是直接通過依賴注入的方式,這個後面再寫咯。現在知道是怎麼回事就 OK 啦!

當然,由於篇幅有限,可能目前你還沒能理解這樣做有什麼好處,可能會有各種疑惑,沒關係,慢慢學習下去就會迎刃而解了。

其他的管理

在沒有 Spring 時,我們需要在程式碼中手動處理一些與業務邏輯無關的問題,比如連線池和事務管理等。而有了 Spring 之後,這些問題都可以通過 Spring 的 API 和元件來解決,從而使程式碼更加簡潔易讀。

總結

Spring 是一個很牛的、開源的 Java 框架,實現了 IoC(Inversion of Control,控制反轉)和 AOP(Aspect Oriented Programming,面向切面程式設計)等功能。

Spring 的核心特點包括便於開發、便於測試、便於整合和便於部署,啥都方便。

Spring 框架的出現簡化了 Java EE(Enterprise Edition)開發的過程。在沒有使用 Spring 的情況下,開發 Java EE 應用程式需要手動建立和管理物件之間的依賴關係,而使用 Spring 可以通過設定和註解來實現物件的自動管理和依賴注入。Spring 還提供了許多其他模組和功能,如資料存取/整合、Web 開發支援、AOP、工具等,使開發人員可以更加便捷地開發企業級應用程式。

總之,學習 Spring 可以幫助我們更好地理解和應用現代企業級 Java 開發的基本概念和最佳實踐,提高開發效率和程式碼質量。

參考

https://docs.spring.io/spring-framework/docs/5.0.0.RC3/spring-framework-reference/overview.html

https://docs.spring.io/spring-framework/docs/5.2.24.RELEASE/spring-framework-reference/overview.html#overview

最後的最後

希望各位螢幕前的靚仔靚女們給個三連!你輕輕地點了個贊,那將在我的心裡世界增添一顆明亮而耀眼的星!

咱們下期再見!