關(guān)于ApplicationContext的啟動流程詳解
ApplicationContext的啟動流程
ApplicationContext
是 Spring IoC 容器的核心接口,它提供了配置、訪問和管理 Bean 的功能。ApplicationContext
的啟動流程可以細(xì)分為以下幾個關(guān)鍵步驟,這些步驟主要在AbstractApplicationContext
類的refresh()
方法中實(shí)現(xiàn):
1. prepareRefresh()
- 準(zhǔn)備刷新:
- 設(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)系解析(忽略某些接口的自動裝配,注冊特殊的依賴項)。
- 注冊一些內(nèi)置的 Bean (例如,
environment
、systemProperties
、systemEnvironment
)。
4. postProcessBeanFactory(beanFactory)
- BeanFactory 后置處理:
- 允許子類對
BeanFactory
進(jìn)行進(jìn)一步的定制。 - 這是一個模板方法,由具體的
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)建一個默認(rèn)的DelegatingMessageSource
。
8. initApplicationEventMulticaster()
- 初始化事件廣播器:
- 初始化應(yīng)用事件廣播器 (
ApplicationEventMulticaster
)。 - 如果在
BeanFactory
中找到名為applicationEventMulticaster
的 Bean,則使用該 Bean;否則,創(chuàng)建一個默認(rèn)的SimpleApplicationEventMulticaster
。
9. onRefresh()
- 刷新 (可選):
- 這是一個模板方法,由具體的
ApplicationContext
實(shí)現(xiàn)類提供具體實(shí)現(xiàn)。 - 例如,
AbstractRefreshableWebApplicationContext
會在這里創(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)聽器容器已刷新。 - 注冊
LiveBeansView
MBean (如果啟用).
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
啟動的核心。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)建和配置,但其核心啟動流程仍然遵循上述步驟。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
自制Java工具實(shí)現(xiàn)翻譯鼠標(biāo)選中文本
這篇文章主要為大家詳細(xì)介紹了如何自制Java工具實(shí)現(xiàn)ctrl+c+c翻譯鼠標(biāo)選中文本,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2024-01-01MPAndroidChart開源圖表庫的使用介紹之餅狀圖、折線圖和柱狀圖
這篇文章主要介紹了MPAndroidChart開源圖表庫的使用介紹之餅狀圖、折線圖和柱狀圖的相關(guān)資料,需要的朋友可以參考下2016-02-02java+jdbc+mysql+socket搭建局域網(wǎng)聊天室
這篇文章主要為大家詳細(xì)介紹了java+jdbc+mysql+socket搭建局域網(wǎng)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01Spring Cloud Gateway使用Token驗(yàn)證詳解
這篇文章主要介紹了Spring Cloud Gateway使用Token驗(yàn)證詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02Java實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能實(shí)例代碼
在這里,我們使用servlet來實(shí)現(xiàn)隨機(jī)驗(yàn)證碼的實(shí)現(xiàn),有需要的朋友可以參考一下2013-08-08