Spring IoC 容器的設計與實現精析,比教材更易理解的詳細解讀在這裏!

1.spring的IOC容器

在 Spring IoC 容器的設計中,容器有兩個系列,能夠當作是容器的具體表現形式:spring

BeanFactory 簡單容器:實現了容器的基本功能,典型方法如 getBean、containsBean、isSingleton;設計模式

ApplicationContext 應用上下文:在簡單容器的基礎上,增長上下文的特性。數據結構

解讀: 爲何要設計兩個系列,而不是一個?這就涉及到架構設計的模式了,底層定義核心流程,上層擴展功能實現,高內聚、低耦合。在架構設計中,這樣的分層是頗有必要的,能夠隨時替換掉一個抽象層。架構

Spring 經過定義 BeanDefinition 來管理基於 Spring 的應用中的各類對象以及它們之間的相互依賴關係。BeanDefinition 抽象了咱們對 Bean 的定義,是讓容器起做用的主要數據類型。IoC容器是用來管理對象依賴關係的,BeanDefinition 就是對依賴反轉模式中管理的對象依賴關係的數據抽象,也是容器實現依賴反轉功能的核心數據結構,依賴反轉功能都是圍繞對這個BeanDefinition的處理來完成的。工具

解讀: BeanDefinition 事實上就是 Bean 的定義在運行時的表現。不管是 xml 配置的 Bean,仍是註解定義的 Bean,又或者是自定義掃描進來的 Bean,最終都經過 BeanDefinition 來承載。若是有自定義的 xml 標籤,解析後也是生成 BeanDefinition 註冊到 IOC 中。這樣設計,IOC 只須要關心 BeanDefinition 便可,極大增長了擴展性和靈活性。當咱們 getBean 的時候,若是 Bean 尚未初始化,容器就會找到 BeanDefinition,而後根據 BeanDefinition 初始化 Bean 及其依賴。架構設計

2.springIOC容器的設計

IoC容器的接口設計如圖所示:設計

BeanFactory 定義了基本的 IoC 容器的規範,包括了 getBean 方法。HierarchicalBeanFactory 接口在繼承了 BeanFactory 後,增長了getParentBeanFactory 方法,使 BeanFactory 具有了雙親IoC容器的管理功能。在接下來的 ConfigurableBeanFactory 中,定義了一些對 BeanFactory 的配置功能,好比經過 setParentBeanFactory 方法設置雙親IoC容器,經過 addBeanPostProcessor 方法配置Bean後置處理器。cdn

解讀:xml

能夠看到 BeanFactory 只定義了基本功能,是一個最核心的容器接口定義。在 BeanFactory 的基礎上 Spring 經過繼承逐層擴充容器的能力。理解如此多的工廠接口就是在理解 Spring 的設計模式,正如前面所說,這裏的繼承關係也是架構分層的體現。經過繼承和擴充,在 ConfigurableBeanFactory 中基本完成了 BeanFactory 系列的接口定義。固然了,接口分層後,BeanFactory 的每一層具體實現也是分層的,後面會具體解讀。這裏能夠看到面向接口開發極大提升了擴展性和靈活性。對象

以 ApplicationContext 爲核心的接口系列中,ListableBeanFactory 和HierarchicalBeanFactory 兩個接口鏈接了 BeanFactory 接口定義和ApplicationConext 應用上下文的接口定義。

在 ListableBeanFactory 接口中,細化了許多 BeanFactory 的接口功能,好比定義了getBeanDefinitionNames 接口方法。對於 ApplicationContext 接口,它經過繼承MessageSource、ResourceLoader、ApplicationEventPublisher 接口,在BeanFactory 的基礎上添加了對高級容器特性的支持。

解讀:

ApplicationContext 繼承了 BeanFactory 接口,具備了容器的基本功能,同時根據上下文的特色,也用 ListableBeanFactory 接口作了功能擴展。上下文與容器的主要區別,仍是體如今容器高級特性上,好比 MessageSource 實現了國際化、ResourceLoader 實現了資源加載、ApplicationEventPublisher 實現了事件機制。所以平時工做中使用上下文會多一點,通常不直接使用 BeanFactory 簡單容器。

3.FactoryBean

在 BeanFactory 中,Bean 是經過 FactoryBean 來獲取的。FactoryBean是一個工廠Bean,能夠生成某一個類型 Bean 的實例,它最大的一個做用是:可讓咱們自定義 Bean 的建立過程。可使用轉義符 「&」 獲得 FactoryBean 自己,用來區分經過容器來獲取 FactoryBean 產生的對象和獲取 FactoryBean 自己。

解讀:

FactoryBean 和 BeanFactory,一個是 Factory,也就是 IOC 容器工廠,一個是特點類型的 Bean。全部的 Bean 都是由 BeanFactory 管理。FactoryBean 是一個能產生或者修飾對象生成的工廠 Bean,它的實現與設計模式中的工廠模式和修飾器模式相似。這兩個類型名稱比較接近,不少人容易混淆,只要記住結尾區分便可,一個是工廠,一個是 Bean。

4.BeanFactory容器的設計原理

BeanFactory 提供了使用 IoC 容器的規範,在這個基礎上,Spring 還提供了符合這個 IoC 容器接口的一系列容器的實現供開發人員使用,以 XmlBeanFactory 的實現爲例來講明簡單IoC容器的設計原理。

解讀:

這裏的 XmlBeanFactory 是一個基於 XML 的容器實現。從類圖能夠看到,容器的實現也是分層的,每一層接口都有對應的實現,每個實現都只作本身職責範圍內的事情,經過繼承造成了一個多層次的容器結構。若是咱們要定義本身的容器實現,只須要像它同樣按需繼承和實現便可。必定要理解分層的意義,這樣才能設計出更好的實現。

DefaultListableBeanFactory 實際上包含了基本IoC容器所具備的重要功能,在Spring中,其實是把 DefaultListableBeanFactory 做爲一個默認的功能完整的 IoC 容器來使用的。XmlBeanFactory 在繼承了 DefaultListableBeanFactory 容器的功能的同時,增長了新的功能,是一個能夠讀取以 XML 文件方式定義的 BeanDefinition 的IoC容器。

解讀:

在繼承體系中,DefaultListableBeanFactory 實現了容器的重要功能。XmlBeanFactory 解決了 XML 文件的解析,並把解析出來的 Bean 定義註冊到容器中。這就是一個逐層實現的設計,繼承了默認的實現後,只須要根據本身的場景作定製便可,每一層的實現都不算複雜。

在 XmlBeanFactory 中,初始化了一個 XmlBeanDefinitionReader,用來讀取以XML方式定義的 BeanDefinition。而 XML 做爲資源文件,經過 Resource 類來封裝 I/O 操 做。XmlBeanDefinitionReader 初始化後,調用 loadBeanDefinitions 方法從Resource 中載入 BeanDefinition。

解讀:

一個真正完整的容器在啓動階段主要作幾個事情:

找到 Bean 定義,如 xml、註解等,若是是資源文件能夠用 Resource 類來封裝,支持 ClassPath、jar、URL 等;

初始化 Reader 注入 Resource,BeanDefinitionReader 接口定義瞭解析相關的方法,Spring 默認提供了不少實現類;

Reader 解析 BeanDefinition,初始化後註冊到容器中。

5.ApplicationContext容器的設計原理

以經常使用的 FileSystemXmlApplicationContext 的實現爲例。主要功能已經在AbstractXmlApplicationContext 中實現了,在 FileSystemXmlApplicationContext中,做爲一個具體的應用上下文,只須要實現和它自身設計相關的兩個功能。

若是應用直接使用 FileSystemXmlApplicationContext,對於實例化這個應用上下文的支持,同時啓動IoC容器的 refresh() 過程。這個 refresh() 過程會牽涉 IoC 容器啓動的一系列複雜操做,同時,對於不一樣的容器實現,這些操做都是相似的,所以在基類中將它們封裝好。因此,咱們在FileSystemXml的設計中看到的只是一個簡單的調用。

解讀:

refresh 是上下文的很重要的一個操做。Spring容器的啓動,初始化一些容器啓動必要的資源,BeanFactory 的建立、初始化,Bean 的建立、初始化、註冊、非懶加載,註冊和設置國際化工具類MessageSource,註冊和設置事件,等一系列過程都在這個 refresh 方法裏面進行調用。關於 refresh 的實現原理,後續會有文章解讀,限於篇幅,這裏就不展開了。

FileSystemXmlApplicationContext 是一個從文件系統加載 XML 的上下文實現,所以

設計了從文件系統中加載XML的功能。

解讀:

能夠看到,Spring 內部上下文的實現和繼承關係很是複雜,難以理解。實際上,按照實現分層的思路去理解仍是比較容易的,每一層只實現本身相關的功能。相似或者公用的能力都往下沉澱變爲底層的基礎能力,上層實現只作調用。看源碼的時候,要有全局視野,哪些是公用能力,哪些是本層次定製功能,這樣就會好理解一點。

相關文章
相關標籤/搜索