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

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

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

 

Spring 通過 IoC 容器來管理所有 Java 物件的例項化和初始化,控制物件與物件之間的依賴關係。

我們將由 IoC 容器管理的 Java 物件稱為 Spring Bean,它與使用關鍵字 new 建立的 Java 物件沒有任何區別。

 

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

 

 

控制反轉(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 的“控制反轉”。

 

 

依賴注入(DI)

 

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

 

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

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

 

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

 

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

 

一個類的物件。

 


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

 

 

 


從程式碼可以看出,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。

 

 

BeanFactory

BeanFactory 是 IoC 容器的基本實現,也是 Spring 提供的最簡單的 IoC 容器,它提供了 IoC 容器最基本的功能,由 org.springframework.beans.factory.BeanFactory 介面定義。

BeanFactory 採用懶載入(lazy-load)機制,容器在載入配置檔案時並不會立刻建立 Java 物件,只有程式中獲取(使用)這個對物件時才會建立。