1. 程式人生 > 實用技巧 >Spring 入門(一):IoC 和 DI

Spring 入門(一):IoC 和 DI

Spring 介紹

什麼是 Spring

Spring 是一個輕量級、非侵入式的框架,提倡以“最少侵入”的方式來管理應用中的程式碼,目的是為了解決企業級應用開發的業務邏輯層和其他各層的耦合問題,最根本的使命是解決企業級應用開發的複雜性,即簡化 Java 開發。

Spring 框架中有兩大核心理念,這兩大核心理念是 Spring 成功的基石:

  • 控制反轉(Inversion of Control,IoC)或者稱為依賴注入(dependency injection,DI)
  • 面向切面程式設計(aspect-oriented programming,AOP)

Spring 框架的設計目標、設計理念和框架核心:

  • 設計目標:為開發者提供一個一站式輕量級應用開發平臺。

  • 設計理念:在 JavaEE 開發中,支援 pojo 和 JavaBean 開發方式,使應用面向介面開發,充分支援面向物件設計方法;通過 IoC 容器實現物件耦合關係的管理,並實現依賴反轉,將物件之間的依賴關係交給 IoC 容器,實現解耦。

  • 框架的核心:IoC 容器和 AOP 模組。通過 IoC 容器管理 pojo 物件以及他們之間的耦合關係;通過 AOP 以動態非侵入的方式增強服務。IoC 讓相互協作的元件保持鬆散的耦合,而 AOP 程式設計允許把遍佈於應用各層的功能分離出來形成可重用的功能元件。


Spring 體系結構

Spring 總共大約有 20 個模組,由 1300 多個不同的檔案構成,而這些元件被整合在以下模組:

☕️ 核心容器(Core Container)

  • Core 模組:提供了框架基本的核心工具類,包括依賴注入 IoC 與 DI 的最基本實現,其它元件都要使用到這個模組的類。

  • Beans 模組:提供了 BeanFactory 介面,是工廠模式的一個經典實現。該模組負責初始化各種 Bean,並呼叫它們的生命週期方法,Spring 將 IoC 容器中的管理物件稱為 Bean。

  • Context 模組:Spring 的上下文,為 Spring 提供執行時環境,儲存物件的狀態。該模組建立在 Core 和 Beans 子模組的基礎之上,提供的 ApplicationContext 介面是 Beans 模組的 BeanFactory 的擴充套件,提供一種框架式的物件訪問方式。

  • SpEL 模組:提供了強大的表示式語言去支援執行時查詢和操作物件圖。

☕️ 資料訪問/整合(Data Access/Integeration)

  • JDBC 模組:提供了一個 JDBC 的封裝,大幅度地減少了在開發過程中對資料庫操作的編碼。
  • ORM 模組:為流行的物件關係對映(Object-Relational Mapping)API 提供整合層,包括 JPA 和Hibernate。
  • OXM 模組:提供了一個支援物件和 XML 對映的抽象層實現,如 JAXB、Castor、JiBX 和 XStream。
  • JMS 模組:指 Java 訊息傳遞服務,包含用於生產和使用訊息的功能。
  • Transactions 模組:事務模組,支援用於實現特殊介面以及所有 POJO 類的程式設計和宣告式事務管理。

☕️ Web

  • Web 模組:提供了基本的 Web 開發整合功能,例如多檔案上傳功能、使用 Servlet 監聽器初始化一個 IOC 容器以及 Web 應用上下文。

  • WebMvc模組:包含用於 Web 應用程式的Spring MVCREST Web Services實現,提供了領域模型程式碼和 Web 表單之間的清晰分離,並與 Spring Framework 的所有其它功能整合。

  • WebSocket 模組:提供了 WebSocket 和 SocketJS 的實現。

  • WebFlux 模組:Spring5 新增模組,是一套全新的Reactive Web棧技術,實現完全非阻塞。

☕️ 其它模組

  • AOP 模組:提供了面向切面程式設計實現,允許定義方法攔截器和切入點,將程式碼按照功能進行分離,以降低耦合性。

  • Aspects 模組:提供了與 AspectJ 的整合功能,AspectJ 是一個功能強大且成熟的面向切面程式設計框架。

  • Instrumentation 模組:提供了類工具的支援和類載入器的實現,可以在特定的應用伺服器中使用。

  • Messaging 模組:提供了對訊息傳遞體系結構和協議的支援。

  • Test 模組:支援使用 JUnit 或 TestNG 對 Spring 元件進行單元測試和整合測試。

Spring 各模組的依賴關係如下圖所示:


Spring 的優缺點

⭐️ Spring 框架的優點:

  • 方便解耦,簡化開發

    通過 Spring 提供的 lOC 容器,可以將物件的建立和依賴關係交由 Spring 進行控制,避免硬編碼所造成的過度耦合,也不必再為單例模式類、屬性檔案解析等這些很底層的需求編寫程式碼,可以更專注於上層的應用。

  • AOP 程式設計的支援

    Spring 提供面向切面程式設計,許多不容易用傳統 OOP 實現的功能可以通過 AOP 輕鬆實現,例如對程式進行許可權攔截、執行監控。

  • 宣告式事務的支援

    只需要通過配置就可以完成對事務的管理,而無需手動程式設計。

  • 方便程式的測試

    Spring 對 Junit4/Junit5 進行了支援,可以通過註解方便的測試 Spring 程式。

  • 方便整合各種優秀框架

    Spring 內部提供了對各種優秀框架的直接支援(如:Struts、Hibernate、MyBatis 等)。

  • 降低 JavaEE API 的使用難度

    Spring 對 JavaEE 開發中非常難用的一些 API(JDBC、JavaMail、遠端呼叫等)提供了封裝,使這些API 應用難度大大降低。

⭐️ Spring 框架的缺點:

  • Spring 依賴反射,反射影響程式執行效能。

IoC & DI 的理解

✏️ IoC 是什麼?

IoC——Inversion of Control,即“控制反轉”,不是一種技術,是一種設計思想

所謂的“控制”,指的是物件的控制,即物件的建立、初始化、銷燬等生命週期的操作;所謂的“控制反轉”,指的是物件的控制權發生反轉,即物件的建立、初始化、銷燬等操作交由 IoC 容器管理,而不是傳統的在你的物件內部直接控制。

在傳統的 Java SE 程式設計中,我們的程式是物件的直接控制者,負責物件的建立、初始化和銷燬;而在 Spring 中,物件的建立、初始化和銷燬交由 IoC 容器負責,我們的程式無法決定物件生命週期的任何一個階段,最多是藉助於 Spring 的擴充套件機制做一些微小的動作。

  • 建立物件:原來是 new 一個物件,現在由 IoC 容器負責建立;
  • 初始化物件:比如 A 依賴 B,原來通過構造器或者 setter 方法賦值,現在由 IoC 容器查詢及注入依賴物件;
  • 銷燬物件:原本直接將物件賦值 null 或者做一些銷燬操作,現在由 IoC 容器管理生命週期負責 銷燬。

也就是說,我們由物件的直接控制者變成了 IoC 容器的被動接受者,物件生命週期的控制權發生了反轉。

✏️ IoC 能做什麼?

IoC 不是一種技術,只是一種思想,一個重要的面向物件程式設計的法則,它能指導我們設計出鬆耦合、更優良的程式。把建立和查詢依賴物件的控制權交給了容器,由容器進行注入組合物件,所以物件與物件之間是鬆散耦合,利於功能複用,更重要的是使得程式的整個體系結構變得非常靈活。

其實 IoC 對程式設計帶來的最大改變不是從程式碼上,而是從思想上,發生了“主從換位”的變化。應用程式原本是老大,要獲取什麼資源都是主動出擊,但是在 IoC/DI 思想中,應用程式就變成被動的了,被動的等待 IoC 容器來建立並注入它所需要的資源了。

✏️ DI 是什麼?

DI——Dependency Injection,即“依賴注入”,是 IoC 的一種重要實現,從 IoC 到 DI,就是從理論到了實踐。

一個物件的建立往往會涉及到其它物件的建立,比如一個物件 A 的成員變數持有著另一個物件 B 的引用,這就是依賴,A 依賴於 B。IoC 機制既然負責了物件的建立,那麼這個依賴關係也就必須由 IoC 容器負責起來,而負責的方式就是 DI——依賴注入。通過將依賴關係寫入配置檔案,然後在建立有依賴關係的物件時,由 IoC 容器負責注入依賴的物件,如在建立 A 時,檢查到有依賴關係,IoC 容器就把 A 依賴的物件 B 建立後注入到 A 中(組裝,通過反射機制實現),然後把 A 返回給物件請求者,完成工作。

理解依賴注入,重點就在於 “依賴”、“注入” 兩個概念。什麼是依賴?物件執行所需要的外部的資料、資源就是依賴,沒有這些東西物件不能完成業務處理,必須拿到才能執行。什麼是注入?注入這個詞真的很形象,就像打針一樣,從外部注入到內部,容器載入了外部的檔案、URL、配置和物件,然後把這些資料、物件按需注入給物件。

✏️ IoC 和 DI 的關係

IoC 和 DI 是同一個概念的不同角度描述,但實際上又是有區別的。IoC 強調的是容器和物件的控制權發生了反轉,而 DI 強調的是物件的依賴由容器進行注入,大部分情況下說兩者相同也不算錯。但是廣義上 IoC 是一種軟體開發模式,也就是說還可以通過別的方式實現,而 DI 只是其中一種,Spring 選擇了 DI 從而使 DI 在 Java 開發中深入人心。


核心介面介紹

BeanFactory 和 ApplicationContext

BeanFactory 和 ApplicationContext 是 Spring 中的兩大核心介面,都可以把他們當做 IoC 容器。其中,ApplicationContext 擴充套件了 BeanFactory 介面,是其子介面。