1. 程式人生 > 其它 >spring——控制反轉(IoC)—— 與 ——依賴注入(DI)

spring——控制反轉(IoC)—— 與 ——依賴注入(DI)

控制反轉(IoC)

在傳統的 Java 應用中,一個類想要呼叫另一個類中的屬性或方法,通常會先在其程式碼中通過 new Object() 的方式將後者的物件創建出來,然後才能實現屬性或方法的呼叫。

為了方便理解和描述,我們可以將前者稱為“呼叫者”,將後者稱為“被呼叫者”。

也就是說,呼叫者掌握著被呼叫者物件建立的控制權。

但在 Spring 應用中,Java 物件建立的控制權是掌握在 IoC 容器手裡的,其大致步驟如下。

  1. 開發人員通過 XML 配置檔案、註解、Java 配置類等方式,對 Java 物件進行定義,例如在 XML 配置檔案中使用 <bean> 標籤、在 Java 類上使用 @Component 註解等。
  2. Spring 啟動時,IoC 容器會自動根據物件定義,將這些物件建立並管理起來。這些被 IoC 容器建立並管理的物件被稱為 Spring Bean。
  3. 當我們想要使用某個 Bean 時,可以直接從 IoC 容器中獲取(例如通過 ApplicationContext 的 getBean() 方法),而不需要手動通過程式碼(例如 new Obejct() 的方式)建立。


IoC 帶來的最大改變不是程式碼層面的,而是從思想層面上發生了“主從換位”的改變。

原本呼叫者是主動的一方,它想要使用什麼資源就會主動出擊,自己建立;但在 Spring 應用中,IoC 容器掌握著主動權,呼叫者則變成了被動的一方,被動的等待 IoC 容器建立它所需要的物件(Bean)。


這個過程在職責層面發生了控制權的反轉,把原本呼叫者通過程式碼實現的物件的建立,反轉給 IoC 容器來幫忙實現,因此我們將這個過程稱為 Spring 的“控制反轉”。

IoC 是 Inversion of Control 的簡寫,譯為“控制反轉”,它不是一門技術,而是一種設計思想,是一個重要的面向物件程式設計法則,能夠指導我們如何設計出鬆耦合、更優良的程式。


Spring 通過 IoC 容器來管理所有 Java 物件的例項化和初始化,控制物件與物件之間的依賴關係。我們將由 IoC 容器管理的 Java 物件稱為 Spring Bean,它與使用關鍵字 new 建立的 Java 物件沒有任何區別。


IoC 容器是 Spring 框架中最重要的核心元件之一,它貫穿了 Spring 從誕生到成長的整個過程。

依賴注入(DI)

在瞭解了 IoC 之後,我們還需要了解另外一個非常重要的概念:依賴注入。


依賴注入(Denpendency Injection,簡寫為 DI)是 Martin Fowler 在 2004 年在對“控制反轉”進行解釋時提出的。

Martin Fowler 認為“控制反轉”一詞很晦澀,無法讓人很直接的理解“到底是哪裡反轉了”,因此他建議使用“依賴注入”來代替“控制反轉”。

在面向物件中,物件和物件之間是存在一種叫做“依賴”的關係。簡單來說,依賴關係就是在一個物件中需要用到另外一個物件,即物件中存在一個屬性,該屬性是另外一個類的物件。

例如,有一個名為 B 的 Java 類,它的程式碼如下。

  1. public class B {
  2. String bid;
  3. A a;
  4. }


從程式碼可以看出,B 中存在一個 A 型別的物件屬性 a,此時我們就可以說 B 的物件依賴於物件 a。而依賴注入就是就是基於這種“依賴關係”而產生的。

我們知道,控制反轉核心思想就是由 Spring 負責物件的建立。在物件建立過程中,Spring 會自動根據依賴關係,將它依賴的物件注入到當前物件中,這就是所謂的“依賴注入”。

依賴注入本質上是 Spring Bean 屬性注入的一種,只不過這個屬性是一個物件屬性而已。

IoC 的工作原理

在 Java 軟體開發過程中,系統中的各個物件之間、各個模組之間、軟體系統和硬體系統之間,或多或少都存在一定的耦合關係。


若一個系統的耦合度過高,那麼就會造成難以維護的問題,但完全沒有耦合的程式碼幾乎無法完成任何工作,這是由於幾乎所有的功能都需要程式碼之間相互協作、相互依賴才能完成。

因此我們在程式設計時,所秉承的思想一般都是在不影響系統功能的前提下,最大限度的降低耦合度。


IoC 底層通過工廠模式、Java 的反射機制、XML 解析等技術,將程式碼的耦合度降低到最低限度,其主要步驟如下。

  1. 在配置檔案(例如 Bean.xml)中,對各個物件以及它們之間的依賴關係進行配置;
  2. 我們可以把 IoC 容器當做一個工廠,這個工廠的產品就是 Spring Bean;
  3. 容器啟動時會載入並解析這些配置檔案,得到物件的基本資訊以及它們之間的依賴關係;
  4. IoC 利用 Java 的反射機制,根據類名生成相應的物件(即 Spring Bean),並根據依賴關係將這個物件注入到依賴它的物件中。


由於物件的基本資訊、物件之間的依賴關係都是在配置檔案中定義的,並沒有在程式碼中緊密耦合,因此即使物件發生改變,

我們也只需要在配置檔案中進行修改即可,而無須對 Java 程式碼進行修改,這就是 Spring IoC 實現解耦的原理。

==============================================================================================

IoC 容器的兩種實現

IoC 思想基於 IoC 容器實現的,IoC 容器底層其實就是一個 Bean 工廠。Spring 框架為我們提供了兩種不同型別 IoC 容器,它們分別是 BeanFactory 和 ApplicationContext。

---------------------------------------------------------------------------------------------------------------------------

ApplicationContext的3個實現類:

BeanFactory和ApplicationContext的區別