【Spring源碼】IOC實現-代碼邏輯


Spring容器的實現

  1. BeanFactory
  2. ApplicationContext

對於XML文件而言,Spring容器的實現過程

  1. XmlBeanFactory
  2. ClassPathXmlApplicationContext

一、XmlBeanFactory 實現 IOC

簡要敘述版

一、讀取配置文件–>解析配置文件–>加載bean
二、讀取配置文件–>對文件進行編碼處理–>使用該編碼作爲輸入流編碼,獲取輸入流–>獲取對XML文件的驗證模式–>加載XML文件,並得到對應的Document–>對bean的處理(默認標籤解析)–>加載bean【知道加載誰–>從緩存加載–>實例化–>檢查加載對象(beanName)對應的配置,沒有就從上級找–>確定初始化策略】

詳細解釋版

1.配置文件的封裝(讀取配置文件,封裝成Resource資源)

 封裝ClassPathResource:讀取Spring配置文件,返回Resource資源

2.解析註冊bean

2.1 封裝資源文件(編碼處理,對參數Resource使用EncodedResource類進行封裝)

2.2 獲取輸入流(從Resource中獲取對應的InputStream,使用上一步編碼作爲輸入流的編碼,構造InputSource)

2.3 (使用前兩步結果) 進入核心代碼

2.3.1 從encodedResource中獲取已經封裝的Resource對象並在此從Resource中獲取其中的inputStream
2.3.2 通過org.xml.sax.InputSource讀取XML文件的方式來準備InputSource對象
2.3.3 (核心)將準備的數據通過參數傳入真正的核心處理部分doLoadBeanDefinitions
   2.3.3.1 獲取對XML文件的驗證模式(DTD & XSD)
   2.3.3.2 加載XML文件,並得到對應的Document
    2.3.3.2.1 創建DocumentBuilderFactory
    2.3.3.2.2 通過DocumentBuilderFactory創建DocumentBuilder
    2.3.3.2.3 解析inputSource來返回Document對象
2.3.3.3 根據返回的Document註冊Bean信息
    2.3.3.3.1 處理profile屬性
    2.3.3.3.2 解析註冊 BeanDefinition【對bean的處理(默認標籤解析)】

3.加載bean

3.1 轉換對應 beanName

3.2 緩存中獲取單例 bean

3.3 從 bean 的實例中獲取對象

3.4 獲取單例

3.5 準備創建 bean

3.6 循環依賴

3.7 創建 bean

3.7.1 創建 bean 的實例
3.7.2 記錄創建 bean 的 ObjectFactory
3.7.3 屬性注入
3.7.4 初始化 bean
3.7.5 註冊 DisposableBean

二、補充內容:

默認標籤解析

(一)bean 標籤

1.解析出配置文件的各種屬性(元素解析,信息提取)

1.1 提取元素中的 id 和 name 屬性
1.2 進一步解析其他所有屬性,統一封裝至GenericBeanDefinition 類型的實例中
  1.2.1 <定義解析完的位置> 創建 BeanDefinition(Bean信息的承載實例)
  1.2.2 <開始解析> 解析各種屬性
1.3 如果檢測到bean沒有指定beanName,那麼使用默認規則爲此 bean 生成 beanName
1.4 將獲取到的信息(解析到的所有屬性,beanName,別名數組)封裝到 BeanDefinitionHolder 的實例中

2.解析自定義標籤

2.1 獲取屬性或者元素的命名空間 --> 判斷該元素或者屬性是否適用於自定義標籤的解析條件
2.2 找出自定義類型所對應的 NamespaceHandler並進一步解析

3.對解析後配置文件的內容進行註冊

3.1 通過 beanName 註冊 BeanDefinition
  3.1.1 對 AbstractBeanDefinition 進行校驗(校驗 methodOverrides屬性)
  3.1.2 對 beanName 已經註冊的情況的處理。如果設置了不允許bean的覆蓋,則需要拋出異常,否則直接覆蓋
  3.1.3 加入 map 緩存
  3.1.4 清除:解析之前留下的對應 beanName 的緩存
3.2 通過別名註冊 BeanDefiniton
  3.2.1 alias 和 beanName 相同:不處理,刪除原有的 alias
  3.2.2 alias 覆蓋:如果 aliasName 已經使用,並已指向另一 beanName,則需要用戶的設置進行處理
  3.2.3 alias 循環檢查:當 A->B 存在時,若再次出現 A->C->B 時,則會拋異常
  3.2.4 註冊 alias

4.通知監聽器,bean已經加載完成(目前 Spring 對此未做處理)

(二)alias(獲取–>註冊)

(三)import

1.獲取 resource 屬性所表示的路徑

2.解析路徑中的系統屬性,格式如“${user.dir}”

3.判定 location 是絕對路徑還是相對路徑

4.如果是絕對路徑:遞歸調用bean的解析過程,進行另一次的解析

5.如果是相對路徑:計算出絕對路徑,進行解析

6.通知監聽器,解析完成

發佈了165 篇原創文章 · 獲贊 97 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章