【死磕 Spring】----- IOC 之註冊解析的 BeanDefinition
DefaultBeanDefinitionDocumentReader.processBeanDefinition()
完成 Bean 標籤解析的核心工作,如下:
解析工作分為三步:1、解析預設標籤;2、解析預設標籤後下得自定義標籤;3、註冊解析後的 BeanDefinition。經過前面兩個步驟的解析,這時的 BeanDefinition 已經可以滿足後續的使用要求了,那麼接下來的工作就是將這些 BeanDefinition 進行註冊,也就是完成第三步。
註冊 BeanDefinition 由BeanDefinitionReaderUtils.registerBeanDefinition()
完成。如下:
首先通過 beanName 註冊 BeanDefinition ,然後再註冊別名 alias。BeanDefinition 的註冊由介面 BeanDefinitionRegistry 定義。
通過 beanName 註冊
BeanDefinitionRegistry.registerBeanDefinition()
實現通過 beanName 註冊 BeanDefinition,如下:
處理過程如下:
-
首先 BeanDefinition 進行校驗,該校驗也是註冊過程中的最後一次校驗了,主要是對 AbstractBeanDefinition 的 methodOverrides 屬性進行校驗
-
根據 beanName 從快取中獲取 BeanDefinition,如果快取中存在,則根據 allowBeanDefinitionOverriding 標誌來判斷是否允許覆蓋,如果允許則直接覆蓋,否則丟擲 BeanDefinitionStoreException 異常
-
若快取中沒有指定 beanName 的 BeanDefinition,則判斷當前階段是否已經開始了 Bean 的建立階段(),如果是,則需要對 beanDefinitionMap 進行加鎖控制併發問題,否則直接設定即可。對於
hasBeanCreationStarted()
方法後續做詳細介紹,這裡不過多闡述。 -
若快取中存在該 beanName 或者 單利 bean 集合中存在該 beanName,則呼叫
resetBeanDefinition()
重置 BeanDefinition 快取。
其實整段程式碼的核心就在於this.beanDefinitionMap.put(beanName,beanDefinition);
。BeanDefinition 的快取也不是神奇的東西,就是定義 map ,key 為 beanName,value 為 BeanDefinition。
註冊 alias
BeanDefinitionRegistry.registerAlias
完成 alias 的註冊。
註冊 alias 和註冊 BeanDefinition 的過程差不多。在最好呼叫了checkForAliasCircle()
來對別名進行了檢測。
如果 name 、 alias 為 1 、3 ,則構成 (1,3),加入集合中存在(A,1)、(3,A)的情況則會出錯。
到這裡 BeanDefinition、alias 都已經注入到快取中,下一步則是等待初始化使用了。
原文釋出時間為:2018-09-28
本文作者:Java技術驛站
本文來自雲棲社群合作伙伴“ ofollow,noindex">Java技術驛站 ”,瞭解相關資訊可以關注“Java技術驛站 ”。