1. 程式人生 > 實用技巧 >Spring IoC 容器 理論基礎

Spring IoC 容器 理論基礎

使用者在使用 Spring 所提供的各種功能之前,必須在 Spring IoC 容器中裝配好 Bean,並建立 Bean 和 Bean 之間的關聯關係

IoC 是什麼

Ioc,Inversion of Control,即“控制反轉”。它不是什麼技術,而是一種設計思想。在 Java 開發中,Ioc 意味著將你設計好的物件交給容器控制,而不是傳統的在你的物件內部直接控制。如何理解好 Ioc 呢?理解好 Ioc 的關鍵是要明確“誰控制誰,控制什麼,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:

  • 誰控制誰,控制什麼:傳統 Java SE 程式設計,我們直接在物件內部通過 new 進行建立物件,是程式主動去建立依賴物件;而 IoC 是有專門一個容器來建立這些物件,即由 IoC 容器來控制物件的建立;誰控制誰?當然是 IoC 容器控制了物件;控制什麼?那就是主要控制了外部資源獲取(不只是物件,還包括檔案等)。

  • 為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程式是由我們自己在物件中主動控制去直接獲取依賴物件,也就是正轉;而反轉則是由容器來幫忙建立及注入依賴物件;為何是反轉?因為由容器幫我們查詢及注入依賴物件,物件只是被動的接受依賴物件,所以是反轉;哪些方面反轉了?依賴物件的獲取被反轉了。

用圖例說明一下,傳統程式設計都是主動去建立相關物件然後再組合起來:

當有了 IoC/DI 的容器後,在客戶端類中不再主動去建立這些物件了,如圖:

IoC 能做什麼

IoC 不是一種技術,只是一種思想,一個重要的面向物件程式設計的法則,它能指導我們如何設計出鬆耦合、更優良的程式。傳統應用程式都是由我們在類內部主動建立依賴物件,從而導致類與類之間高耦合,難於測試;有了 IoC 容器後,把建立和查詢依賴物件的控制權交給了容器,由容器進行注入組合物件,所以物件與物件之間是鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程式的整個體系結構變得非常靈活。

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

IoC 很好的體現了面向物件設計法則之一的好萊塢法則:“別找我們,我們找你”。即由 IoC 容器幫物件找相應的依賴物件並注入,而不是由物件主動去找。

IoC 和 DI

DI,Dependency Injection,即“依賴注入”:是元件之間依賴關係由容器在執行期決定,形象的說,即由容器動態的將某個依賴關係注入到元件之中。依賴注入的目的並非為軟體系統帶來更多功能,而是為了提升元件重用的頻率,併為系統搭建一個靈活、可擴充套件的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何程式碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。

理解 DI 的關鍵是:“誰依賴誰,為什麼需要依賴,誰注入誰,注入了什麼”。我們來深入分析一下:

  • 誰依賴於誰:當然是某個容器管理物件依賴於 IoC 容器;“被注入物件的物件”依賴於“依賴物件”。
  • 為什麼需要依賴:容器管理物件需要 IoC 容器來提供物件需要的外部資源。
  • 誰注入誰:很明顯是 IoC 容器注入某個物件,也就是注入“依賴物件”。
  • 注入了什麼:就是注入某個物件所需要的外部資源,包括物件、資源、常量資料。

IoC 和 DI 有什麼關係呢?其實它們是同一個概念的不同角度描述,由於控制反轉概念比較含糊(可能只是理解為容器控制物件這一個層面,很難讓人想到誰來維護物件關係),所以 2004 年大師級人物 Martin Fowler 又給出了一個新的名字:“依賴注入”,相對 IoC 而言,“依賴注入”明確描述了“被注入物件依賴 IoC 容器配置依賴物件”。

IoC 容器

IoC 容器就是具有依賴注入功能的容器,IoC 容器負責例項化、定位、配置應用程式中的物件及建立這些物件間的依賴。應用程式無需直接在程式碼中 new 相關的物件,應用程式由 IoC 容器進行組裝。在 Spring 中 BeanFactory 是 IoC 容器的實際代表者。

Spring IoC 容器如何知道哪些是它管理的物件呢?

這就需要配置檔案,Spring IoC 容器通過讀取配置檔案中的配置元資料,通過元資料對應用中的各個物件進行例項化及裝配。一般使用基於 xml 配置檔案進行配置元資料,而且 Spring 與配置檔案完全解耦的,可以使用其他任何可能的方式進行配置元資料,比如註解、基於 java 檔案的、基於屬性檔案的配置都可以。

在 Spring Ioc 容器的代表就是 org.springframework.beans 包中的 BeanFactory 介面,BeanFactory 介面提供了 IoC 容器最基本功能;而 org.springframework.context 包下的 ApplicationContext 介面擴充套件了 BeanFactory,還提供了與 Spring AOP 整合、國際化處理、事件傳播及提供不同層次的 context 實現,如針對 web 應用的 WebApplicationContext。簡單說,BeanFactory 提供了 IoC 容器最基本功能,而 ApplicationContext 則增加了更多支援企業級功能支援。ApplicationContext 完全繼承 BeanFactory,因而 BeanFactory 所具有的語義也適用於 ApplicationContext。

  • XmlBeanFactory:BeanFactory 實現,提供基本的 IoC 容器功能,可以從 classpat h 或檔案系統等獲取資源。
Resource resource = new ClassPathResource("classpath.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
  • ClassPathXmlApplicationContext:ApplicationContext 實現,從 classpath 獲取配置檔案。

  • FileSystemXmlApplicationContext:ApplicationContext 實現,從檔案系統獲取配置檔案。