1. 程式人生 > >Spring 原始碼學習 04:初始化容器與 DefaultListableBeanFactory

Spring 原始碼學習 04:初始化容器與 DefaultListableBeanFactory

#### 前言 ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/Sf8fRH-D6nt5n.png) 在前一篇文章:[建立 IoC 容器的幾種方式](https://mp.weixin.qq.com/s/V7SjmIFKAXyppBF_KHbxXQ)中,介紹了四種方式,這裡以 `AnnotationConfigApplicationContext` 為例,跟進程式碼,看看 IoC 的啟動流程。 ### 入口 從 JavaConfig 中載入配置的 `AnnotationConfigApplicationContext` 啟動方式如下: ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/NbaqT1-SIKlXs.png) 進去之後發現構造其實是呼叫的當前無參構造。 ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/dA7SqR-pnWaJ0.png) 所以在啟動時也可以直接宣告無參構造,改寫為下面這種: ```java public class AnnotationConfigApplicationTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(JavaConfig.class); context.refresh(); System.out.println(context.getBean(UserComponent.class)); } } ``` 今天就研究研究無參構造這一部分究竟做了什麼邏輯! #### 無參構造 ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/VfQDRi-qtFJay.png) 其中的 `StartupStep` 是 5.3 新增的類,看程式碼註釋的意思是:表示用來記錄啟動過程中的一些指標資訊等。暫時不做研究。 主要研究紅框部分!注意,**這一塊並不代表只有紅框部分**! ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/jHZiO9-lClEgy.png) 因為 `AnnotationConfigApplicationContext` 繼承了 `GenericApplicationContext`,所以會先執行父類的構造方法。 ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/T9dF4r-BeA6nA.png) 所以這裡會建立一個 `DefaultListableBeanFactory` 的容器。 ### DefaultListableBeanFactory ![DefaultListableBeanFactory UML](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/DefaultListableBeanFactory-oBHX69.png) 雖然說 Spring 的 `BeanFactory` 定義了容器的基礎概念、介面方法等,但是 `DefaultListableBeanFactory` 才是一個真正可以 new 出來的具體的容器,當然也可以暫且稱之為 bean 工廠。 下面來看一下 `DefaultListableBeanFactory` 裡面都有什麼? ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/oUgw6b-dgE9ZX.png) 在 `DefaultListableBeanFactory` 裡面會初始化很多引數,其中重點關注的是下面兩個引數: ```java /** Map of bean definition objects, keyed by bean name. */ // BeanDefinition 的儲存 Map 其中 key 為 beanName private final Map beanDefinitionMap = new ConcurrentHashMap<>(256); /** List of bean definition names, in registration order. */ // BeanName 的集合 private volatile List beanDefinitionNames = new ArrayList<>(256); ``` 其中 `BeanDefinition` 描述了一個 bean 例項,該例項具有屬性值,建構函式引數值以及具體實現所提供的更多資訊。 對應的 `beanDefinitionMap` 就是儲存的初始化的 beanName 和 BeanDefinition。 至於 BeanDefinition 具體內容,下一節再做介紹。 ### 總結 通過上面的閱讀,可以在初始化流程中增加一部分模組,即例項化 `DefaultListableBeanFactory` ![](https://cdn.jsdelivr.net/gh/liuzhihang/oss/pic/article/m4P5ZW-VrZwt7.png) 再回顧一下 `DefaultListableBeanFactory` 的概念。 >**DefaultListableBeanFactory:** > >Spring 的 ConfigurableListableBeanFactory 和 BeanDefinitionRegistry 介面的預設實現:基於bean定義元資料的成熟bean工廠,可通過後處理器進行擴充套件。 >重點需要把握的是 DefaultListableBeanFactory 內部定義了 BeanDefinition 的 Map。 #### 結束語 本文從入口開始,進入到構造,主要介紹了 `DefaultListableBeanFactory` 的建立,及建立時初始化了一堆引數。 考慮到文章篇幅問題,儘量避免大段大段的貼程式碼以及註釋,有興趣的小夥伴可以試著自己搭建原始碼構建環境,然後 Debug 走一走,這樣也可以互相探討,共同學習。 筆者也是剛開始閱讀學習原始碼,不足之處,希望多多指正。 #### 相關推薦 - [Spring 原始碼學習 03:建立 IoC 容器的幾種方式](https://mp.weixin.qq.com/s/V7SjmIFKAXyppBF_KHbxXQ) - [Spring 原始碼學習 02:關於 Spring IoC 和 Bean 的概念](https://mp.weixin.qq.com/s/YPDPU7ePtii0vlrynexb_w) - [Spring 原始碼學習 01:原始碼閱讀環境的搭建](https://mp.weixin.qq.com/s/gDhJMSPSX2vz68p5