Spring-IOC學習-02 IOC容器初始化

上次說到spring IOC 過程當中的幾個重要接口: Resource, BeanDefinition, BeanDefinitionRender ,BeanFactory, ApplicationContext spring

簡單說了spring 的bean初始化流程:由 Resource接口的具體實現定位,讀取資源文件。交給BeanfinintionRender進行bean的解析解析獲得spa

 bean的描述對象BeanDefinition 。最後 BeanDefinitionRegister 會將已經等到的bean註冊到 BeanFactory 容器中去完成bean的實例化xml

過程。對象

首先請看一個簡單使用Spring的代碼:blog

  

不知道有沒有這樣使用過spring呢!這正是上面所說的spring在IOC初始化時的三個步驟。這樣的獲取是否是讓你更明白IOC的初始化脈絡?繼承

咱們能夠將 IOC容器初始化(bean的實例化) 過程分爲 3 個部分 A:資源文件的定位  B:bean的解析,加載  C:bean的"註冊"將解析後的BeanDefinition對象註冊到BeanFactory接口

中去.(該初始化過程是不包涵Bean 的依賴注入的 ,什麼時候完成依賴呢? )  慢慢往下看吧......資源

 

步驟1: BeanDefinition 資源文件的定位。get

  上次說到spring 中有個重要的接口Resource 該接口負責Spring 資源文件的加載讀取等操做.Reource根據不一樣的文件類型定位BeanDefinition。源碼

還記得FileSystemResource,ClassPathResource這倆個子類嗎?他們都是 Resource 的具體實現。分別讀取不一樣路徑下的資源文件獲取BeanDefinition

  查看上面的代碼Spring  經過Resource 來定位BeanDefinition資源文件,而後在使用BeanDefinitionRender來將定位的資源文件處理後獲得Spring要使用的BeanDefinition

對象。由於咱們使用的是單純的容器僅僅是一個能裝載 bean 的容器而已因此對於要使用什麼樣的Resource,什麼樣的BeanDefinitioRender都是由咱們本身說了算的,因此這裏就

很靈活了可是,由於什麼都要本身定製工做量就上來了。

  爲何會這麼說?還記得ApplicationContext這個NB的接口嗎?找個具體實現去看看吧爲啥我們在使用spring提供的這個接口的時候不用這寫額外操做呢?由於別人辦理作了呀看

看別人怎麼作的吧!

  

怎麼樣很簡單吧!!!!

既然他已經獲得了具體的Resource,那麼FileSystemApplicationContext是怎樣進行數據處理的,他是如何初始化BeanDefinition,BeanDefinitionRender的呢?查看該類並無香瓜的代碼,

僅包含多個構造的重載方法,還有這個定位資源文件的方法 getResourceByPath(....);

那麼只有向他的父類找答案了! 在 AbstractRefreshableWebApplicationContext 中找到了答案! 看看FileSystemXmlApplicationContext的繼承關係

 

  查看到AbstractRefreshableWebApplicationContext類的時候發了問題看一下refreshBeanFactory()方法吧!

 該方法建立了 DefaultListableBeanFactory beanFactory = createBeanFactory();  一個IOC 容器用來承載解析的BeanDefinition,容器有了那麼BeanDefinition,和BeanDefinitionRender在哪裏呢 ?

回想一下文章開始的時候建立IOC的代碼 建立好了工廠以後接着作了什麼操做,ok如今是Resource,BeanFactory  接着就該BeanDefinitionRender( factory ) ;,還有他的loadBeanDefinitions(resource);

就能夠完成BeanDefinition的定位,載入了。這裏依然是   loadBeanDefinitions(beanFactory);

是否是和剛纔咱們本身獲取很相近呢?  原來BeanDefinitionRender,BeanDefinition等都是在父類中執行的載入Bean 的操做固然這是合理的由於對於bean的定位來講不一樣的只是文件的路徑也就是path用說不

同而已,那麼具體的路徑交給具體的子類來實現就ok了,由子類本身來肯定使用的資源。

 

2:BeanDefinition的載入,解析過程

   FileSystemXmlApplicationContext.refresh();方法初始化BeanDefinition的入口方法。該方法會調用AbstractRefreshableApplicationContext中的refreshBeanFactory();方法完成 容器的建立 BeanDefinitionRender的初始化BeanDefinition載入等操做

在refreshBeanFactory()方法中會調用 loadBeanDefinitions(beafactory); 該方法由根據不一樣的具體實現調用不一樣。此處調用的是  AbstractXmlApplicationContext中的 loadBeanDefinitions(beafactory);具體實現

最後調用loadBeanDefinitions(XmlBeaDefinitionRender);來載入bean的操做,調用了一系列 loadBeanDefinitions()方法;雖然參數不同可是不注意的話容易出錯,具體解析xml的方法是 XmlBeaDefinitionRender中的doLoadBeanDefinitions(InputSource , Resource ) ;方法完成bean的載入,解析操做。

spring 在什麼時候將解析的bean信息封裝成了本身的 BeanDefinition對象呢?

 

 這是在BeanDefinitionDocumentRender類中執行的經過 proccessBeanDefinitions( Elelment elt , BeanDefinitionParserDelegate delegate );

最終處理beanDefinition是由BeanDefinitionParserDelegate對象來執行的 處理完成後會產生一個BeanDefinitionHolder對象該對象包涵了BeanDefinition信息還有一些額外信息好比別名等信息

具體的標籤解析是調用該類中的 parseBeanDefinitionElement(...) ,parseProppertyElements()....等parse方法進行的xml解析在該類中源碼體現就不細說了。

完成解析後就獲得了DeanDefinitionHolder對象就獲得了BeanDefintion的信息。就此bean的載入就完成了!

 

3:將已經解析好的BeanDefinition註冊到Ioc容器中去.

   這一步就是將上面解析獲得的beanDefinition對象放到一個map中去.此時的beanDefinition已經可使用了可是依賴關係還沒有完成。

相關文章
相關標籤/搜索