Spring容器的實現
- BeanFactory
- ApplicationContext
對於XML文件而言,Spring容器的實現過程
- XmlBeanFactory
- 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