一塊兒來讀Spring源碼吧(二)容器getBean過程詳解

上一篇分析了XmlBeanFactory的初始化過程,此時配置的bean已註冊到容器中,但也僅僅只是保存了bean的信息,並無產生bean實例。下面咱們以BeanFactory.getBean(String name)爲出發點探索下bean的加載過程。緩存

AbstractBeanFactory實現了getBean方法,調用doGetBean真正開始獲取bean。
首先是將參數name轉化爲beanName,若是是「&」開頭的表明是FactoryBean(是特殊的bean,後面會講到)須要把「&」去除;若是是別名就去尋找它最終指向的beanName。
而後從容器的單例註冊中心嘗試獲取bean實例。順序以下:從單例緩存中(容器的singletonObjects屬性)嘗試獲取;若是沒有就從提前曝光單例對象(容器的earlySingletonObjects屬性)嘗試獲取;若是尚未,就從singletonFactories中嘗試獲取這個bean的ObjectFactory,再調用ObjectFactory.getObject()獲取到bean,放入earlySingletonObjects,把ObjectFactory從singletonFactories中移除(是否是很混亂?別急,這是Spring爲了不循環依賴作出的策略,後面咱們會解釋)。
若是沒有獲取到,也就是說要新建一個,先檢查bean是否已經在原型建立中(避免原型的循環依賴),再在容器中查找是否存在beanName對應的BeanDefinition,找不到的話就遞歸從父容器查找;而後若是BeanDefinition有依賴(也就是bean定義時有depends-n屬性)就先把依賴關係註冊到容器的dependentBeanMap,再遞歸加載依賴的bean;而後根據BeanDefinition設置的scope選擇建立單例、原型仍是其餘scope的bean實例。單例的話調用getSingleton建立單例;原型的須要先把beanName註冊到容器的prototypesCurrentlyInCreation中(爲了防止循環依賴)而後調用createBean建立bean實例,隨後從prototypesCurrentlyInCreation找中移除beanName。建立出的實例跟前面在緩存中獲取到的同樣並不會直接返回,而是調用getObjectForBeanInstance,若是不是FactoryBean或者想要的就是FactoryBean自己(name是&開頭)就直接返回;不然先從工廠建立bean緩存factoryBeanObjectCache中嘗試獲取,沒有就調用getObjectFromFactoryBean方法建立一個bean實例(是單例還會存入factoryBeanObjectCache)返回。一大堆流程看下來是否是有點暈,讓咱們再來簡述下步驟:
一、name轉化爲beanName
二、嘗試從緩衝中獲取單例
2.一、單例緩存singletonObjects中查找(這個getSingleton只查找不建立)
2.二、提前曝光單例earlySingletonObjects中查找
2.三、singletonFactories中查找ObjectFactory並在生產bean放入earlySingletonObjects後移除
三、緩衝中獲取不到,須要新建
3.一、當前容器中查找BeanDefinition
3.二、沒有的話去父容器中查找BeanDefinition
3.三、遞歸加載設置過的依賴bean
3.四、根據scope建立bean實例
四、若是是工廠bean,返回生產的bean
4.一、嘗試從緩存factoryBeanObjectCache中獲取
4.二、調用BeanFactory.getObject()生產一個bean實例
4.三、若是不是應用程序自己的bean,調用後置處理器(這個後面會重點說)
4.四、是單例的話存入factoryBeanObjectCacheapp

如今咱們大體瞭解了向容器獲取一個bean的主要步驟,可是咱們仍是不太清楚具體是怎麼建立bean實例的,因此咱們還須要繼續深刻:
前面說到若是是單例的話,調用getSingleton(String beanName, ObjectFactory<?> singletonFactory)(區別於2.1的getSingleton),先從singletonObjects查找,沒有的話將beanName放入singletonsCurrentlyInCreation表示該bean正在加載;而後用參數singletonFactory的函數方法createBean(對,就是和原型同樣的那個)建立一個bean;將beanName從singletonsCurrentlyInCreation中移除;最後將新創建的beanName和bean的映射關係保存到緩存singletonObjects和已註冊registeredSingletons中,移除singletonFactories和earlySingletonObjects中的記錄。步驟簡述以下:
3.4.一、從singletonObjects查找
3.4.二、設置正在加載狀態
3.4.三、createBean建立bean
3.4.四、移除正在加載狀態
3.4.五、保存緩存,刪除中間輔助狀態ide

咱們再來看createBean。先從BeanDefinition中獲取bean的Class,再對override屬性(經過lookup-method和replace-method配置,後面實例化時會用到)進行標記和驗證,而後給後置處理器一個機會直接返回bean代理,即若是容器中有註冊InstantiationAwareBeanPostProcessor這類後置處理器的話,就分別執行它的postProcessBeforeInstantiation和全部後置處理器的postProcessAfterInstantiation,若是返回不爲空就直接返回代理bean(AOP功能基於這裏判斷的);最後調用doCreateBean實例化bean。步驟簡述以下:
3.4.3.一、從BeanDefinition中獲取bean的Class對象
3.4.3.二、對override屬性進行標記和驗證
3.4.3.三、初始化前的短路判斷
3.4.3.四、實例化bean函數

繼續深刻doCreateBean,第一步判斷若是是單例的話從factoryBeanInstanceCache中獲取緩存的BeanWrapper(bean的包裝類)並從中移除,若是沒有則調用createBeanInstance建立一個BeanWrapper;而後應用MergedBeanDefinitionPostProcessor(AutowiredAnnotationBeanPostProcessor,Autowired);容許循環依賴的而且自身在建立中的單例,把此單例的ObjectFactory(SmartInstantiationAwareBeanPostProcessor,AOP)註冊到singletonFactories,同時從earlySingletonObjects移除對應;而後調用populateBean對bean的屬性進行填充,遞歸初始依賴的bean;再調用initializeBean執行初始化方法;對於容許循環依賴的而且自身在建立中的單例作循環依賴檢查;最後註冊DisposableBean。步驟簡述以下:
3.4.3.4.一、嘗試從factoryBeanInstanceCache中獲取緩存BeanWrapper
3.4.3.4.二、建立一個bean實例返回BeanWrapper
3.4.3.4.三、應用MergedBeanDefinitionPostProcessor
3.4.3.4.四、依賴處理
3.4.3.4.五、屬性填充
3.4.3.4.六、執行初始化方法
3.4.3.4.七、循環依賴檢查
3.4.3.4.八、註冊DisposableBean
首先咱們看如何建立一個bean實例。先是解析出Class,若是工廠方法不用空,即設置了factory-method,則使用工廠方法初始化策略;不然須要根據參數鎖定構造函數,若是已經解析過了在緩存中能夠找到鎖定,不然進行解析鎖定並加入緩存;沒有鎖定到有參數的構造函數的話,就使用默認構造器,若是有須要覆蓋或動態替換的方法(override屬性)須要使用CGLIB進行動態代理,不然就用反射的方式建立實例。
再來看一下屬性填充。在屬性設置前應用InstantiationAwareBeanPostProcessors的postProcessAfterInstantiation(能夠控制是否繼續填充),而後根據設置的自動注入方式(名稱或者類型)獲取屬性bean(遞歸getBean)存入PropertyValues中,再應用InstantiationAwareBeanPostProcessors的postProcessProperties對填充前的屬性進行處理(如對屬性的驗證),最後將全部PropertyValues中的屬性填充到BeanWrapper中。
屬性填充完以後就是initializeBean方法了。首先對實現XXAware接口的bean注入相應的資源(如實現了BeanFactoryAware的bean會注入當前BeanFactory的實例),而後就是註冊了的BeanPostProcessor的postProcessBeforeInitialization,再是激活自定義的init方法,前後執行實現了InitializingBean的afterPropertiesSet方法和配置init-method方法。
最後看下DisposableBean的註冊。註冊DisposableBean的實現,在註銷時執行來源於DestructionAwareBeanPostProcessors、實現的DisposableBean的destroy方法還有本身配置的destroy-method的處理。圖片描述post

相關文章
相關標籤/搜索