源碼角度,理清spring IOC容器初始化的全過程

IOC容器初始化過程中4個比較重要的類

1.BeanFactory系列:只實現IOC容器的基本功能

BeanFactory的基本功能:

a.通過containBean方法判斷IOC容器中是否含有指定名字的Bean

b.通過isSingleton方法查詢指定名字的Bean是否爲Singleton類型的Bean

c.通過isPrototype方法查詢指定名字的Bean是否爲Prototype類型的Bean

d.通過isTypeMatch方法查詢指定了名字的BeanClass類型是否是特定的Class類型

e.通過getType方法查詢指定名字的BeanClass類型

f.通過getAliases方法查詢指定名字的Bean的所有別名

g.通過getBean方法獲取指定name或指定Class類型的Bean對象


2.ApplicationContext系列:高級容器,在簡單容器的基礎上增加了許多對應用框架、環境的適配,是IOC容器的高級表現形式

ApplicationContext的新特性:

a.支持不同的信息源:擴展了MessageSource接口,可支持國際化實現,爲多語言版本應用提供服務

b.訪問資源:繼承了ResourceLoader接口,可從不同的I/O途徑得到Bean定義資源

c.支持應用事件:繼承了ApplicationEvenPublisher接口,在上下文中引入事件機制,這些事件和Bean的生命週期結合爲Bean的管理提供了便利

3.Resource系列:由於jdk提供的如URLFile等不足以支持spring獲取各種不同來源的資源的操作(如缺少從類路徑或web容器上下文獲取資源),因此spring框架提供了一個更爲可靠的接口Resource用來抽象規範各種不同來源的資源,主要實現類如下:


4.BeanDefinition:管理基於spring的應用中的各種對象以及它們之間的依賴關係,是對依賴反轉模式中管理的對象依賴關係的數據抽象,是容器實現依賴反轉功能的核心數據結構

FactoryBean與BeanFactory的區別

FactoryBean:產生對象的工廠,不是一個簡單的Bean,是能產生or修飾對象生成的工廠Bean

BeanFactoryIOC容器,所有Bean都是由其管理的

使用容器時,可使用&”來得到FactoryBean本身,用於區分通過容器獲取的是FactoryBean產生的對象還是FactoryBean對象本身

IOC容器的接口設計,如下圖


圖摘自《spring技術內幕:深入解析spring架構與設計原理》

IOC容器的初始化過程

主要包括BeanDefinitionResource定位、載入和註冊這3個過程

Resource定位:指BeanDefinition的資源定位,由ResourceLoader通過統一的Resource接口來完成

BeanDefinition的載入:將用戶定義好的Bean表示成IOC容器內部的數據結構

BeanDefinition的註冊:通過BeanDefinitionRegistry接口的實現來完成,將上一步驟解析得到的BeanDefinitionIOC容器進行註冊

1. BeanDefinitionResource定位:


refresh方法的具體實現在父類AbstractApplicationContext中,具體如下:

refreshBeanFactory具體實現在子類AbstractRefreshableApplicationContext中,具體如下:

loadBeanDefinition的具體實現在子類AbstractXmlApplicationContext中,具體如下:

XmlBeanDefinitionReader類中讀取BeanDefinition信息,具體如下:

DefaultResourceLoader類中完成對Resource的定位,具體如下:

crtl+T看下getResourceByPath方法的實現關係,會發現FileSystemXmlApplicationContext實現了該方法,於是Resource的定位走了一圈回到了FileSystemXmlApplicationContext類中,生成並返回了一個FileSystemResource


通過FileSystemResource對象,spring便可以進行相關的I/O操作,完成BeanDefinition定位,該過程實現的就是對path進行解析後生成一個FileSystemResource對象返回的過程,至此,BeanDefinition定位的過程便完成了

2.Resource的載入:

載入過程是在XmlBeanDefinitionReader中實現的(FileSystemXmlApplicationContext使用的是xml方式的定義,若是其他不同的定義,則採用其他BeanDefinitionReader),載入之前XmlBeanDefinitionReader的父類AbstractXmlBeanDefinition已爲BeanDefinition的載入做好準備,實現在AbstractXmlBeanDefinition中,具體如下:

上面的loadBeanDefinitions(Resource resource)方法具體實現在子類XmlBeanDefinitionReader中,在讀取器中,需得到代表xml文件的Resource對象,因Resource對象封裝了對xml文件的I/O操作,讀取器便可以在打開I/O流後得到xml的文件對象,得到文件對象後就可以按照springBean的定義規則來對該xml文檔進行解析,具體解析在BeanDefinitionParserDelegate中完成(有興趣可以看,反正我是不看額)

XmlBeanDefinitionReader中看下loadBeanDefinitions(Resource resource)方法具體是如何實現BeanDefinition載入的:

springBeanDefinition如何按照springBean語義要求進行解析並轉化爲容器內部數據結構的,這個過程是在BeanDefinitionDocumentReader類中完成的,具體如下:

BeanDefinitionHolder封裝很簡單,如下:

到此,Resource的載入就完成了,主要分爲2部分,先是通過DefaultDocumentLoader解析xml文件得到Document對象,這些Document對象只是通用的xml解析對象,並不是按照springBean規則進行解析的;完成通用的xml解析後,使用BeanDefinitionDocumentReader按照springBean規則進行解析,具體解析是在BeanDefinitionParserDelegate中完成的,解析結果由BeanDefinitionHolder對象持有,最後使用BeanDefinitionHolderIOC容器註冊BeanDefinition信息

3. Resource的註冊:

Resource註冊的入口在DefaultBeanDefinitionDocumentReader中,如下:

BeanDefinitionReaderUtils中:

其中的BeanDefinitionRegistry其實就是DefaultListableBeanFactory,因爲其實現了BeanDefinitionRegistry接口

DefaultListableBeanFactory中其實就是使用一個ConcurrentHashMap來持有載入的BeanDefinition對象的,BeanDefinition的註冊的具體實現在DefaultListableBeanFactory中,如下:

別名的註冊是在SimpleAliasRegistry類中實現的,具體如下:

到此,IOC容器的BeanDefinition的註冊就已經完成了,整個IOC容器的初始化過程也完畢,DefaultListableBeanFactory中已經建立了整個Bean的配置信息,IOC容器的責任就是對這些信息進行維護和處理,這些信息是IOC容器建立依賴反轉的基礎



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章