spring源碼分析系列4:ApplicationContext研究
- 2019 年 10 月 12 日
- 筆記
ApplicationContext介面
首先看一下一個最基本的上下文應該是什麼樣子
ApplicationContext介面的注釋里寫的很清楚:
一個基本applicationContext應該提供:
- 訪問Bean的能力
- 提供載入資源的能力
- 發布事件的能力
- 解析消息、支援國際化的能力
AbstractApplicationContext承上啟下
ConfigurableApplicationContext介面:
大部分上下文都實現了此介面. 此介面除了繼承了ApplicaitnContext介面的能力外. 還具有可配置上下文與生命周期管理功能.
其中最重要的是定義了refresh()方法. refresh()功能是載入配置.
AbstractApplicationContext抽象類:
大部分上下文都繼承了此類.AbstractApplicationContext可以說啟到承上啟下的作用.
從繼承圖我們看, AbstractApplicationContext實現了大部分的介面方法.
其中refresh()方法的實現.為ApplicationContext提供了載入配置的能力.
載入的什麼配置呢?
其實:所謂載入的配置大部分都是載入Bean
ApplicationContext與BeanFactory關係
上節分析了BeanFactory存儲BeanDefinition與Bean. 並且BeanFactory的createBean()方法可以將BeanDefinition創建成Bean.
要想從BeanFactory中獲取Bean,就得先有BeanDefinition. 有了BeanDefinition,還要觸發BeanDefinition到Bean的創建.
這裡就產生了兩個問題:
- BeanDefinition從哪裡來?
- 創建過程在哪裡觸發的?
ApplicationContext扮演的角色也就顯而易見了.
ApplicationContext初始化的核心工作是將散落在各個目錄下的各種配置形式的Bean定義,搜集起來解析成BeanDefinition併入庫到BeanFactory.然後觸發BeanDefinition創建成Bean,存到BeanFactory中
至此: 整個spring啟動的脈絡就也清晰了. 兩大塊:Bean定義的搜集+Bean的創建
.
[開發人員]--標註-->[Bean定義] --搜集--> [BeanDefinition] --創建-->[Bean]
ApplicationContext重要工作
開發人員常用的標註Bean定義的方式有.
- xml文件標註Bean定義
- 註解標註Bean定義
ApplicationContext將這些Bean定義轉為BeanDefinition並不是那麼容易.
第一步搜集:需要把散落的Bean定義的載體找到.搜集起來.(注意,ApplicationContext搜集Bean定義的過程其實也是通過調用工具來執行的)
- XML對應的有XmlBeanDefinitionReader 搜集器
- 註解JavaConfig對應的有ClassPathBeanDefinitionScanner收集器
第二步解析.將XML或者JavaConfig中的標註了Bean定義的轉為BeanDefinition
第三步:擴展點.BeanFactoryPostProcessor.實現了此介面的類可以在BeanDefinition入庫到BeanFactory的這個階段中,修改BeanDefinition資訊.這也是spring留下的擴展點。
BeanDefinitionRegistryPostProcessor與BeanFactoryPostProcessor與BeanPostProcessor區別:
- BeanFactoryPostProcessor:可以修改BeanDefinition。發生在BeanDefinition入庫到BeanFactory階段.
- BeanDefinitionRegistryPostProcessor繼承與BeanFactoryPostProcessor:單從名字上看,我們可以看出,這個PostProcessor跟BeanDefinition註冊有關。他發生的階段比BeanFactoryPostProcessor更早,他用來註冊BeanDefinition用。實現了此介面的可以看作一個BeanDefinition掃描註冊器。
- BeanPostProcessor: 發生在BeanDefinition創建Bean階段。
總結:
BeanDefinition是物料
Bean是成品
BeanFactory 存儲物料,存儲成品.
ApplicationContext初始化: 搜集物料,入庫到BeanFactory, 並觸發非懶載入成品的創建.
歡迎大家關注我的公眾號【源碼行動】,最新個人理解及時奉送。