Spring:源碼解讀Spring IOC原理

一、什麼是Ioc/DI?
IoC 容器:最主要是完成了完成對象的創建和依賴的管理注入等等。先從我們自己設計這樣一個視角來考慮:所謂控制反轉,就是把原先我們代碼裏面需要實現的對象創建、依賴的代碼,反轉給容器來幫忙實現。那麼必然的我們需要創建一個容器,同時需要一種描述來讓容器知道需要創建的對象與對象的關係。這個描述最具體表現就是我們可配置的文件。對象和對象關係怎麼表示?可以用 xml , properties 文件等語義化配置文件表示。描述對象關係的文件存放在哪裡?可能是 classpath , filesystem ,或者是 URL 網絡資源, servletContext 等。回到正題,有了配置文件,還需要對配置文件解析。不同的配置文件對對象的描述不一樣,如標準的,自定義聲明式的,如何統一? 在內部需要有一個統一的關於對象的定義,所有外部的描述都必須轉化成統一的描述定義。
如何對不同的配置文件進行解析?需要對不同的配置文件語法,採用不同的解析器
二、 Spring IOC體系結構?
(1) BeanFactory
Spring Bean的創建是典型的工廠模式,這一系列的Bean工廠,也即IOC容器為開發者管理對象間的依賴關係提供了很多便利和基礎服務,在Spring中有許多的IOC容器的實現供用戶選擇和使用,其相互關係如下:

其中BeanFactory作為最頂層的一個接口類,它定義了IOC容器的基本功能規範,BeanFactory 有三個子類:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。但是從上圖中我們可以發現最終的默認實現類是 DefaultListableBeanFactory,他實現了所有的接口。那為何要定義這麼多層次的接口呢?查閱這些接口的源碼和說明發現,每個接口都有他使用的場合,它主要是為了區分在 Spring 內部在操作過程中對象的傳遞和轉化過程中,對對象的數據訪問所做的限制。例如 ListableBeanFactory 接口表示這些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是這些 Bean 是有繼承關係的,也就是每個Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定義 Bean 的自動裝配規則。這四個接口共同定義了 Bean 的集合、Bean 之間的關係、以及 Bean 行為。最基本的IOC容器接口BeanFactory

public interface BeanFactory {    
     
     //對FactoryBean的轉義定義,因為如果使用bean的名字檢索FactoryBean得到的對象是工廠生成的對象,    
     //如果需要得到工廠本身,需要轉義           
     String FACTORY_BEAN_PREFIX = "&"; 
        
     //根據bean的名字,獲取在IOC容器中得到bean實例    
     Object getBean(String name) throws BeansException;    
   
     //根據bean的名字和Class類型來得到bean實例,增加了類型安全驗證機制。    
      Object getBean(String name, Class requiredType) throws BeansException;    
     
     //提供對bean的檢索,看看是否在IOC容器有這個名字的bean    
      boolean containsBean(String name);    
     
     //根據bean名字得到bean實例,並同時判斷這個bean是不是單例    
     boolean isSingleton(String name) throws NoSuchBeanDefinitionException;    
     
     //得到bean實例的Class類型    
     Class getType(String name) throws NoSuchBeanDefinitionException;    
     
     //得到bean的別名,如果根據別名檢索,那麼其原名也會被檢索出來    
    String[] getAliases(String name);    
     
 }

在BeanFactory里只對IOC容器的基本行為作了定義,根本不關心你的bean是如何定義怎樣加載的。正如我們只關心工廠里得到什麼的產品對象,至於工廠是怎麼生產這些對象的,這個基本的接口不關心。而要知道工廠是如何產生對象的,我們需要看具體的IOC容器實現,spring提供了許多IOC容器的實現。比如XmlBeanFactory,ClasspathXmlApplicationContext等。其中XmlBeanFactory就是針對最基本的ioc容器的實現,這個IOC容器可以讀取XML文件定義的BeanDefinition(XML文件中對bean的描述),如果說XmlBeanFactory是容器中的屌絲,ApplicationContext應該算容器中的高帥富。ApplicationContext是Spring提供的一個高級的IoC容器,它除了能夠提供IoC容器的基本功能外,還為用戶提供了以下的附加服務。從ApplicationContext接口的實現,我們看出其特點:

  • 1.  支持信息源,可以實現國際化。(實現MessageSource接口)
  • 2.  訪問資源。(實現ResourcePatternResolver接口,這個後面要講)
  • 3.  支持應用事件。(實現ApplicationEventPublisher接口)

(2) BeanDefinition

SpringIOC容器管理了我們定義的各種Bean對象及其相互的關係,Bean對象在Spring實現中是以BeanDefinition來描述的,其繼承體系如下:

Bean 的解析過程非常複雜,功能被分的很細,因為這裡需要被擴展的地方很多,必須保證有足夠的靈活性,以應對可能的變化。Bean 的解析主要就是對 Spring 配置文件的解析。這個解析過程主要通過下圖中的類完成:

三、IoC容器的初始化?

IoC容器的初始化包括BeanDefinition的Resource定位、載入和註冊這三個基本的過程。我們以ApplicationContext為例講解,ApplicationContext系列容器也許是我們最熟悉的,因為web項目中使用的XmlWebApplicationContext就屬於這個繼承體系,還有ClasspathXmlApplicationContext等,其繼承體系如下圖所示:

ApplicationContext允許上下文嵌套,通過保持父上下文可以維持一個上下文體系。對於bean的查找可以在這個上下文體系中發生,首先檢查當前上下文,其次是父上下文,逐級向上,這樣為不同的Spring應用提供了一個共享的bean定義環境。下面我們分別簡單地演示一下兩種ioc容器的創建過程

1、XmlBeanFactory(屌絲IOC)的整個流程

通過XmlBeanFactory的源碼,我們可以發現:

 

 

 

其中BeanFactory作為最頂層的一個接口類,它定義了IOC容器的基本功能規範,BeanFactory 有三個子類:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。但是從上圖中我們可以發現最終的默認實現類是 DefaultListableBeanFactory,他實現了所有的接口。那為何要定義這麼多層次的接口呢?查閱這些接口的源碼和說明發現,每個接口都有他使用的場合,它主要是為了區分在 Spring 內部在操作過程中對象的傳遞和轉化過程中,對對象的數據訪問所做的限制。例如 ListableBeanFactory 接口表示這些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是這些 Bean 是有繼承關係的,也就是每個Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定義 Bean 的自動裝配規則。這四個接口共同定義了 Bean 的集合、Bean 之間的關係、以及 Bean 行為.

最基本的IOC容器接口BeanFactory

Tags: