關(guān)于ApplicationContext的啟動(dòng)流程詳解
ApplicationContext的啟動(dòng)流程
ApplicationContext是 Spring IoC 容器的核心接口,它提供了配置、訪問和管理 Bean 的功能。ApplicationContext的啟動(dòng)流程可以細(xì)分為以下幾個(gè)關(guān)鍵步驟,這些步驟主要在AbstractApplicationContext類的refresh()方法中實(shí)現(xiàn):
1. prepareRefresh()
- 準(zhǔn)備刷新:
- 設(shè)置啟動(dòng)時(shí)間戳。
- 設(shè)置容器的激活狀態(tài)。
- 初始化屬性源 (property sources),用于解析占位符(例如,
${...})。 - 驗(yàn)證必需的屬性(如果有)。
- 創(chuàng)建并保存早期事件監(jiān)聽器集合 (early application listeners).
2. obtainFreshBeanFactory()
- 獲取 BeanFactory:
- 如果存在舊的
BeanFactory,則銷毀其中的 Bean 并關(guān)閉舊的BeanFactory。 - 創(chuàng)建新的
BeanFactory(通常是DefaultListableBeanFactory)。 - 設(shè)置
BeanFactory的序列化 ID (如果需要)。 - 定制
BeanFactory(例如,設(shè)置類加載器、添加后置處理器等)。 - 加載 Bean 定義 (調(diào)用
loadBeanDefinitions方法):XmlBeanDefinitionReader: 從 XML 配置文件加載。AnnotatedBeanDefinitionReader: 從注解配置類加載。ClassPathBeanDefinitionScanner: 掃描類路徑并加載帶有注解的 Bean。
3. prepareBeanFactory(beanFactory)
- 準(zhǔn)備 BeanFactory:
- 設(shè)置
BeanFactory的類加載器。 - 設(shè)置表達(dá)式解析器 (用于解析 SpEL 表達(dá)式)。
- 設(shè)置屬性編輯器注冊器。
- 添加內(nèi)置的
BeanPostProcessor(例如,ApplicationContextAwareProcessor、ApplicationListenerDetector等)。 - 配置依賴關(guān)系解析(忽略某些接口的自動(dòng)裝配,注冊特殊的依賴項(xiàng))。
- 注冊一些內(nèi)置的 Bean (例如,
environment、systemProperties、systemEnvironment)。
4. postProcessBeanFactory(beanFactory)
- BeanFactory 后置處理:
- 允許子類對
BeanFactory進(jìn)行進(jìn)一步的定制。 - 這是一個(gè)模板方法,由具體的
ApplicationContext實(shí)現(xiàn)類(如AnnotationConfigApplicationContext)提供具體實(shí)現(xiàn)。
5. invokeBeanFactoryPostProcessors(beanFactory)
- 調(diào)用 BeanFactoryPostProcessor:
- 調(diào)用所有已注冊的
BeanFactoryPostProcessor(包括BeanDefinitionRegistryPostProcessor)。- 先調(diào)用實(shí)現(xiàn)了
PriorityOrdered接口的。 - 再調(diào)用實(shí)現(xiàn)了
Ordered接口的。 - 最后調(diào)用普通的
BeanFactoryPostProcessor。
- 先調(diào)用實(shí)現(xiàn)了
BeanFactoryPostProcessor可以在 Bean 實(shí)例化之前修改 BeanFactory 的配置元數(shù)據(jù)。BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口,它可以在Bean 定義加載完成后,但在 Bean 實(shí)例化之前執(zhí)行,允許添加、刪除或修改 Bean 定義。
6. registerBeanPostProcessors(beanFactory)
- 注冊 BeanPostProcessor:
- 注冊所有實(shí)現(xiàn)了
BeanPostProcessor接口的 Bean。- 先注冊實(shí)現(xiàn)了
PriorityOrdered接口的。 - 再注冊實(shí)現(xiàn)了
Ordered接口的。 - 最后注冊普通的
BeanPostProcessor。 - 重新注冊內(nèi)部的
BeanPostProcessor(MergedBeanDefinitionPostProcessor).
- 先注冊實(shí)現(xiàn)了
BeanPostProcessor可以在 Bean 初始化前后進(jìn)行處理。
7. initMessageSource()
- 初始化 MessageSource:
- 初始化國際化消息源 (
MessageSource)。 - 如果在
BeanFactory中找到名為messageSource的 Bean,則使用該 Bean;否則,創(chuàng)建一個(gè)默認(rèn)的DelegatingMessageSource。
8. initApplicationEventMulticaster() - 初始化事件廣播器:
- 初始化應(yīng)用事件廣播器 (
ApplicationEventMulticaster)。 - 如果在
BeanFactory中找到名為applicationEventMulticaster的 Bean,則使用該 Bean;否則,創(chuàng)建一個(gè)默認(rèn)的SimpleApplicationEventMulticaster。
9. onRefresh()
- 刷新 (可選):
- 這是一個(gè)模板方法,由具體的
ApplicationContext實(shí)現(xiàn)類提供具體實(shí)現(xiàn)。 - 例如,
AbstractRefreshableWebApplicationContext會(huì)在這里創(chuàng)建或刷新 Servlet 上下文。
10. registerListeners()
- 注冊監(jiān)聽器:
- 將之前收集的早期應(yīng)用事件監(jiān)聽器 (early application listeners) 和在容器中定義的監(jiān)聽器注冊到事件廣播器 (
ApplicationEventMulticaster)。 - 發(fā)布早期的應(yīng)用事件 (early application events).
11. finishBeanFactoryInitialization(beanFactory)
- 完成 BeanFactory 初始化:
- 初始化類型轉(zhuǎn)換器 (
ConversionService),如果存在名為conversionService的 Bean。 - 凍結(jié)配置(不允許再修改 Bean 定義)。
- 實(shí)例化所有剩余的非懶加載的單例 Bean (調(diào)用
beanFactory.preInstantiateSingletons())。
12. finishRefresh()
- 完成刷新:
- 清空資源緩存 (例如,
ResourceBundleMessageSource的緩存)。 - 初始化生命周期處理器 (
LifecycleProcessor),如果存在名為lifecycleProcessor的 Bean。 - 調(diào)用
LifecycleProcessor的onRefresh()方法。 - 發(fā)布
ContextRefreshedEvent事件,通知所有監(jiān)聽器容器已刷新。 - 注冊
LiveBeansViewMBean (如果啟用).
13. 異常處理和重置
- 如果在
refresh()過程中發(fā)生異常, 則銷毀已經(jīng)創(chuàng)建的單例 Bean. - 重置容器的激活狀態(tài).
總結(jié)流程圖:
+-----------------------+
| start() |
+-----------------------+
|
V
+-----------------------+
| refresh() |
+-----------------------+
|
V
+-----------------------+
| prepareRefresh() | (準(zhǔn)備刷新)
+-----------------------+
|
V
+-----------------------+
| obtainFreshBeanFactory()| (獲取 BeanFactory, 加載 Bean 定義)
+-----------------------+
|
V
+-----------------------+
| prepareBeanFactory() | (準(zhǔn)備 BeanFactory)
+-----------------------+
|
V
+-----------------------+
|postProcessBeanFactory()| (BeanFactory 后置處理, 可選)
+-----------------------+
|
V
+-----------------------+
|invokeBeanFactoryPPs()| (調(diào)用 BeanFactoryPostProcessor)
+-----------------------+
|
V
+-----------------------+
|registerBeanPostPrcs()| (注冊 BeanPostProcessor)
+-----------------------+
|
V
+-----------------------+
| initMessageSource() | (初始化 MessageSource)
+-----------------------+
|
V
+-----------------------+
|initApplicationEventM()| (初始化事件廣播器)
+-----------------------+
|
V
+-----------------------+
| onRefresh() | (刷新, 可選)
+-----------------------+
|
V
+-----------------------+
| registerListeners() | (注冊監(jiān)聽器)
+-----------------------+
|
V
+-----------------------+
|finishBeanFactoryInit()| (完成 BeanFactory 初始化, 實(shí)例化單例 Bean)
+-----------------------+
|
V
+-----------------------+
| finishRefresh() | (完成刷新, 發(fā)布 ContextRefreshedEvent)
+-----------------------+
|
V
+-----------------------+
| 容器就緒 |
+-----------------------+關(guān)鍵點(diǎn):
refresh()方法是ApplicationContext啟動(dòng)的核心。BeanFactory是實(shí)際創(chuàng)建和管理 Bean 的組件。BeanDefinition描述了如何創(chuàng)建和配置 Bean。BeanFactoryPostProcessor可以在 Bean 實(shí)例化之前修改 BeanFactory 的配置元數(shù)據(jù)。BeanPostProcessor可以在 Bean 初始化前后進(jìn)行處理。ApplicationListener可以監(jiān)聽容器發(fā)布的事件。- Spring Boot 在 Spring Framework 的基礎(chǔ)上,進(jìn)一步簡化了
ApplicationContext的創(chuàng)建和配置,但其核心啟動(dòng)流程仍然遵循上述步驟。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
自制Java工具實(shí)現(xiàn)翻譯鼠標(biāo)選中文本
這篇文章主要為大家詳細(xì)介紹了如何自制Java工具實(shí)現(xiàn)ctrl+c+c翻譯鼠標(biāo)選中文本,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2024-01-01
MPAndroidChart開源圖表庫的使用介紹之餅狀圖、折線圖和柱狀圖
這篇文章主要介紹了MPAndroidChart開源圖表庫的使用介紹之餅狀圖、折線圖和柱狀圖的相關(guān)資料,需要的朋友可以參考下2016-02-02
java+jdbc+mysql+socket搭建局域網(wǎng)聊天室
這篇文章主要為大家詳細(xì)介紹了java+jdbc+mysql+socket搭建局域網(wǎng)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
通過RedisTemplate連接多個(gè)Redis過程解析
這篇文章主要介紹了通過RedisTemplate連接多個(gè)Redis過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
Spring Cloud Gateway使用Token驗(yàn)證詳解
這篇文章主要介紹了Spring Cloud Gateway使用Token驗(yàn)證詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02
Java實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能實(shí)例代碼
在這里,我們使用servlet來實(shí)現(xiàn)隨機(jī)驗(yàn)證碼的實(shí)現(xiàn),有需要的朋友可以參考一下2013-08-08

