關(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è)置屬性編輯器注冊(cè)器。
- 添加內(nèi)置的
BeanPostProcessor(例如,ApplicationContextAwareProcessor、ApplicationListenerDetector等)。 - 配置依賴關(guān)系解析(忽略某些接口的自動(dòng)裝配,注冊(cè)特殊的依賴項(xiàng))。
- 注冊(cè)一些內(nèi)置的 Bean (例如,
environment、systemProperties、systemEnvironment)。
4. postProcessBeanFactory(beanFactory)
- BeanFactory 后置處理:
- 允許子類對(duì)
BeanFactory進(jìn)行進(jìn)一步的定制。 - 這是一個(gè)模板方法,由具體的
ApplicationContext實(shí)現(xiàn)類(如AnnotationConfigApplicationContext)提供具體實(shí)現(xiàn)。
5. invokeBeanFactoryPostProcessors(beanFactory)
- 調(diào)用 BeanFactoryPostProcessor:
- 調(diào)用所有已注冊(cè)的
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)
- 注冊(cè) BeanPostProcessor:
- 注冊(cè)所有實(shí)現(xiàn)了
BeanPostProcessor接口的 Bean。- 先注冊(cè)實(shí)現(xiàn)了
PriorityOrdered接口的。 - 再注冊(cè)實(shí)現(xiàn)了
Ordered接口的。 - 最后注冊(cè)普通的
BeanPostProcessor。 - 重新注冊(cè)內(nèi)部的
BeanPostProcessor(MergedBeanDefinitionPostProcessor).
- 先注冊(cè)實(shí)現(xiàn)了
BeanPostProcessor可以在 Bean 初始化前后進(jìn)行處理。
7. initMessageSource()
- 初始化 MessageSource:
- 初始化國(guó)際化消息源 (
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()
- 注冊(cè)監(jiān)聽器:
- 將之前收集的早期應(yīng)用事件監(jiān)聽器 (early application listeners) 和在容器中定義的監(jiān)聽器注冊(cè)到事件廣播器 (
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)聽器容器已刷新。 - 注冊(cè)
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()| (注冊(cè) BeanPostProcessor)
+-----------------------+
|
V
+-----------------------+
| initMessageSource() | (初始化 MessageSource)
+-----------------------+
|
V
+-----------------------+
|initApplicationEventM()| (初始化事件廣播器)
+-----------------------+
|
V
+-----------------------+
| onRefresh() | (刷新, 可選)
+-----------------------+
|
V
+-----------------------+
| registerListeners() | (注冊(cè)監(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)一步簡(jiǎn)化了
ApplicationContext的創(chuàng)建和配置,但其核心啟動(dòng)流程仍然遵循上述步驟。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot使用Redisson時(shí)候進(jìn)行Redis事務(wù)回滾方式
這篇文章主要介紹了SpringBoot使用Redisson時(shí)候進(jìn)行Redis事務(wù)回滾方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05
解決idea中javaweb的mysql8.0.15配置問題
這篇文章主要介紹了idea中javaweb的mysql8.0.15配置問題 ,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
java對(duì)象序列化與反序列化的默認(rèn)格式和json格式使用示例
這篇文章主要介紹了java對(duì)象序列化與反序列化的默認(rèn)格式和json格式使用示例,需要的朋友可以參考下2014-02-02
Java數(shù)組與堆棧相關(guān)知識(shí)總結(jié)
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java數(shù)組與堆棧展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
spring?boot使用攔截器修改請(qǐng)求URL域名?換?IP?訪問的方法
Spring Interceptor是一個(gè)非常類似于Servlet Filter 的概念 ,這篇文章主要介紹了spring?boot使用攔截器修改請(qǐng)求URL域名?換?IP?訪問的相關(guān)知識(shí),需要的朋友可以參考下2022-09-09
Java實(shí)現(xiàn)規(guī)則幾何圖形的繪制與周長(zhǎng)面積計(jì)算詳解
隨著計(jì)算機(jī)的發(fā)展,人們對(duì)圖形的計(jì)算要求會(huì)越來(lái)越高。在各行各業(yè)中的計(jì)算人員會(huì)對(duì)圖形的計(jì)算要有便利的要求,規(guī)則幾何圖形問題求解程序應(yīng)運(yùn)而生!本文將用Java編寫一個(gè)程序,可以實(shí)現(xiàn)規(guī)則幾何圖形的繪制與周長(zhǎng)面積計(jì)算,感興趣的可以了解一下2022-07-07
java中超過long范圍的超大整數(shù)相加算法詳解(面試高頻)
這篇文章主要介紹了java中超過long范圍的超大整數(shù)相加算法(面試高頻),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08

