Spring Boot 應(yīng)用程序啟動時執(zhí)行完整流程(最新推薦)
關(guān)于Spring Boot 應(yīng)用程序啟動時 main 方法的完整執(zhí)行流程。我會按照方法調(diào)用的核心順序進(jìn)行描述,并解釋每個關(guān)鍵方法的作用。
核心流程總覽
在Spring Boot應(yīng)用中,我們通常會寫一個包含main方法的類,并調(diào)用SpringApplication.run。
示例代碼:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
整個啟動過程可以概括為:構(gòu)造 SpringApplication 對象 -> 執(zhí)行 run 方法 -> 啟動內(nèi)嵌服務(wù)器 -> 完成應(yīng)用啟動。
第一階段:SpringApplication實例化
執(zhí)行方法:new SpringApplication(primarySources)
執(zhí)行
this(null, primarySources):- 作用:調(diào)用內(nèi)部的構(gòu)造器。
- 最主要的部分是
WebApplicationType.deduceFromClasspath()方法:- 這個方法的作用是:根據(jù)類路徑下存在的類來推斷應(yīng)用類型。
- 它會檢查
DispatcherHandler、DispatcherServlet、Servlet等類的存在性,從而判斷應(yīng)用是REACTIVE(響應(yīng)式)、SERVLET(標(biāo)準(zhǔn)的 Servlet Web 應(yīng)用)還是NONE(非 Web 應(yīng)用)。我們最常見的 Spring MVC 應(yīng)用就是SERVLET類型。
執(zhí)行
setInitializers方法:- 作用:設(shè)置應(yīng)用初始化器 (
ApplicationContextInitializer)。 - 最主要的部分是
getSpringFactoriesInstances(ApplicationContextInitializer.class)方法:- 這個方法的作用是:使用 Spring 工廠加載機(jī)制,從
META-INF/spring.factories配置文件中加載并實例化所有配置的ApplicationContextInitializer實現(xiàn)類。 - 常見的初始化器如
ConfigurationWarningsApplicationContextInitializer(檢查配置警告)、ContextIdApplicationContextInitializer(設(shè)置上下文 ID)等。這些初始化器會在ApplicationContext刷新之前被調(diào)用。
- 這個方法的作用是:使用 Spring 工廠加載機(jī)制,從
- 作用:設(shè)置應(yīng)用初始化器 (
執(zhí)行
setListeners方法:- 作用:設(shè)置應(yīng)用監(jiān)聽器 (
ApplicationListener)。 - 最主要的部分同樣是
getSpringFactoriesInstances(ApplicationListener.class)方法:- 這個方法的作用是:從
spring.factories中加載并實例化所有配置的ApplicationListener。 - 這些監(jiān)聽器用于監(jiān)聽在應(yīng)用啟動過程中發(fā)布的各類事件,例如
ApplicationStartedEvent、ApplicationReadyEvent等。ClearCachesApplicationListener(清除緩存)、FileEncodingApplicationListener(檢查文件編碼)都是常見的監(jiān)聽器。
- 這個方法的作用是:從
- 作用:設(shè)置應(yīng)用監(jiān)聽器 (
執(zhí)行
deduceMainApplicationClass方法:- 作用:推導(dǎo)出主應(yīng)用程序類(即我們寫了
main方法的那個類)。 - 原理是:遍歷當(dāng)前調(diào)用棧,找到第一個方法名為
main的類。
- 作用:推導(dǎo)出主應(yīng)用程序類(即我們寫了
至此,SpringApplication 對象構(gòu)造完畢,它已經(jīng)準(zhǔn)備好了初始化器和監(jiān)聽器。
第二階段:執(zhí)行run方法
執(zhí)行方法:SpringApplication.run(primarySources, args)
這是整個啟動流程最核心、最復(fù)雜的方法。
執(zhí)行
getRunListeners方法并調(diào)用listeners.starting():- 作用:獲取
SpringApplicationRunListeners并發(fā)布ApplicationStartingEvent事件。 - 說明:
SpringApplicationRunListeners是SpringApplicationRunListener的集合,它專門用于監(jiān)聽SpringApplication的run方法執(zhí)行過程中的關(guān)鍵節(jié)點。第一步就是發(fā)布應(yīng)用正在啟動的事件。
- 作用:獲取
執(zhí)行
prepareEnvironment方法:- 作用:準(zhǔn)備和應(yīng)用環(huán)境 (
Environment),這是整個應(yīng)用配置的基礎(chǔ)。 - 最主要的部分是:
getOrCreateEnvironment():根據(jù)應(yīng)用類型創(chuàng)建StandardEnvironment或StandardServletEnvironment。configureEnvironment(environment, args):配置環(huán)境,包括PropertySources(屬性源,如 JVM 系統(tǒng)屬性、操作系統(tǒng)環(huán)境變量)和Profiles(配置文件,如 “dev”, “prod”)。listeners.environmentPrepared(environment):發(fā)布ApplicationEnvironmentPreparedEvent事件。這是一個極其重要的擴(kuò)展點,監(jiān)聽這個事件的監(jiān)聽器(最著名的是ConfigFileApplicationListener)會從application.properties、application.yml等文件中加載我們自定義的配置屬性。
- 作用:準(zhǔn)備和應(yīng)用環(huán)境 (
執(zhí)行
printBanner方法:- 作用:在控制臺打印 Spring Boot 的 Banner。
執(zhí)行
createApplicationContext方法:- 作用:創(chuàng)建
ApplicationContext(IoC 容器)。 - 根據(jù)第一步推斷出的
WebApplicationType,創(chuàng)建不同類型的上下文。對于 Servlet Web 應(yīng)用,會創(chuàng)建AnnotationConfigServletWebServerApplicationContext。
- 作用:創(chuàng)建
執(zhí)行
prepareContext方法:- 作用:準(zhǔn)備上面創(chuàng)建好的
ApplicationContext。 - 最主要的部分是:
postProcessApplicationContext(context):后處理應(yīng)用上下文,例如設(shè)置 Bean 名稱生成器、資源加載器。applyInitializers(context):應(yīng)用初始化器。調(diào)用在第一步中加載的所有ApplicationContextInitializer的initialize方法,允許我們在容器刷新前對上下文進(jìn)行自定義。listeners.contextPrepared(context):發(fā)布ApplicationContextInitializedEvent事件,通知監(jiān)聽器上下文已準(zhǔn)備就緒。load(context, sources.toArray(new Object[0])):將主源(即我們的@SpringBootApplication注解類)加載到上下文中,為后續(xù)的組件掃描和 Bean 定義注冊做準(zhǔn)備。listeners.contextLoaded(context):發(fā)布ApplicationPreparedEvent事件,通知監(jiān)聽器上下文已加載完畢。
- 作用:準(zhǔn)備上面創(chuàng)建好的
第三階段:刷新應(yīng)用上下文 (最最核心)
執(zhí)行方法:refreshContext(context)
這個方法內(nèi)部會調(diào)用 AbstractApplicationContext.refresh(),這是 Spring 框架容器初始化的標(biāo)準(zhǔn)流程。
執(zhí)行
prepareRefresh()方法:- 作用:刷新前的準(zhǔn)備工作,例如初始化屬性源、驗證必要的屬性。
執(zhí)行
obtainFreshBeanFactory()方法:- 作用:獲取或刷新內(nèi)部的
BeanFactory(DefaultListableBeanFactory)。BeanFactory是 Spring 容器的基礎(chǔ)。
- 作用:獲取或刷新內(nèi)部的
執(zhí)行
prepareBeanFactory(beanFactory)方法:- 作用:準(zhǔn)備
BeanFactory,配置它的類加載器、后置處理器等標(biāo)準(zhǔn)配置。
- 作用:準(zhǔn)備
執(zhí)行
postProcessBeanFactory(beanFactory)方法:- 作用:允許在 Bean 定義加載完成后、實例化之前,對
BeanFactory進(jìn)行后處理。這是一個空方法,供子類擴(kuò)展。
- 作用:允許在 Bean 定義加載完成后、實例化之前,對
執(zhí)行
invokeBeanFactoryPostProcessors(beanFactory)方法:- 作用:這是 Spring Boot 自動配置的魔法入口!
- 最主要的部分是:調(diào)用所有
BeanFactoryPostProcessor。 - 其中,
ConfigurationClassPostProcessor會解析@Configuration注解的類。它會發(fā)現(xiàn)我們的主類上的@SpringBootApplication注解。 @SpringBootApplication中包含@EnableAutoConfiguration,后者會導(dǎo)入AutoConfigurationImportSelector。AutoConfigurationImportSelector會從META-INF/spring.factories中加載所有EnableAutoConfiguration鍵對應(yīng)的自動配置類(如DataSourceAutoConfiguration,WebMvcAutoConfiguration)。- 這些自動配置類根據(jù)條件(如類路徑下是否存在某個類、是否設(shè)置了某個屬性等)決定是否生效,并向容器中批量添加 Bean 定義。
執(zhí)行
registerBeanPostProcessors(beanFactory)方法:- 作用:注冊
BeanPostProcessor。這些處理器會在 Bean 實例化之后、初始化前后 被調(diào)用,用于對 Bean 進(jìn)行增強(qiáng)(如@Autowired,@PostConstruct等功能都是通過BeanPostProcessor實現(xiàn)的)。
- 作用:注冊
執(zhí)行
initMessageSource()方法:- 作用:初始化國際化相關(guān)的消息源。
執(zhí)行
initApplicationEventMulticaster()方法:- 作用:初始化應(yīng)用事件廣播器,用于事件發(fā)布。
執(zhí)行
onRefresh()方法:- 作用:這是 Spring Boot 創(chuàng)建并啟動內(nèi)嵌 Web 服務(wù)器的關(guān)鍵步驟!
- 在
ServletWebServerApplicationContext中,此方法被重寫。 - 最主要的部分是
createWebServer()方法:- 這個方法的作用是:從
BeanFactory中獲取ServletWebServerFactory(如TomcatServletWebServerFactory)。 - 調(diào)用
factory.getWebServer(...)方法,這會創(chuàng)建內(nèi)嵌的 Tomcat/Jetty/Undertow 服務(wù)器實例,并初始化 Servlet 容器(初始化DispatcherServlet并注冊到容器中)。此時,Web 服務(wù)器已經(jīng)創(chuàng)建好,但尚未開始監(jiān)聽端口。
- 這個方法的作用是:從
執(zhí)行
registerListeners()方法:- 作用:注冊監(jiān)聽器,將事件監(jiān)聽器注冊到第 8 步初始化的事件廣播器中。
執(zhí)行
finishBeanFactoryInitialization(beanFactory)方法:- 作用:完成
BeanFactory的初始化,實例化所有剩余的非懶加載單例 Bean。 - 這是 IoC 容器依賴注入發(fā)生的主要階段。我們的 Controller、Service、Repository 等組件都在這個階段被創(chuàng)建和裝配。
- 作用:完成
執(zhí)行
finishRefresh()方法:- 作用:完成上下文的刷新工作,發(fā)布最終事件。
- 最主要的部分是:
publishEvent(new ContextRefreshedEvent(this)):發(fā)布ContextRefreshedEvent事件。- 在
ServletWebServerApplicationContext中,還會調(diào)用finishRefresh()的一個擴(kuò)展,最終啟動內(nèi)嵌的 Web 服務(wù)器(例如TomcatWebServer.start()),開始監(jiān)聽指定的端口。至此,我們的應(yīng)用已經(jīng)可以處理 HTTP 請求了。
第四階段:啟動后處理
- 執(zhí)行
afterRefresh(context, applicationArguments)方法:- 作用:刷新后處理,默認(rèn)為空。是一個擴(kuò)展點。
- 執(zhí)行
listeners.started(context)方法:- 作用:發(fā)布
ApplicationStartedEvent事件,通知所有監(jiān)聽器應(yīng)用已啟動。
- 作用:發(fā)布
- 執(zhí)行
callRunners(applicationArguments)方法:- 作用:調(diào)用
ApplicationRunner和CommandLineRunner接口的實現(xiàn)類。 - 這是開發(fā)者可以在應(yīng)用啟動后、開始接收流量前,執(zhí)行一些特定初始化邏輯的常用方式。
- 作用:調(diào)用
- 執(zhí)行
listeners.ready(context, timeTaken)方法:- 作用:發(fā)布
ApplicationReadyEvent事件。這個事件標(biāo)志著應(yīng)用已完全啟動完畢,處于就緒狀態(tài)。它與ApplicationStartedEvent的區(qū)別在于,此時所有 Bean 都已初始化,內(nèi)嵌服務(wù)器已在運行。 - 返回
ApplicationContext: - 作用:將已經(jīng)完全初始化好的
ApplicationContext返回。
- 作用:發(fā)布
總結(jié)
整個流程從 main 方法開始,經(jīng)歷了 環(huán)境準(zhǔn)備 -> 容器創(chuàng)建 -> Bean定義加載(自動配置) -> Bean實例化(依賴注入) -> 內(nèi)嵌服務(wù)器啟動 -> 運行自定義初始化邏輯 等一系列復(fù)雜而精密的步驟,最終將一個功能完備的 Spring Boot 應(yīng)用呈現(xiàn)在我們面前。其中 refreshContext() 是整個流程的心臟,而自動配置和內(nèi)嵌服務(wù)器是 Spring Boot 兩大核心特性的實現(xiàn)關(guān)鍵。
到此這篇關(guān)于Spring Boot 應(yīng)用程序啟動時執(zhí)行流程的文章就介紹到這了,更多相關(guān)Spring Boot 啟動時執(zhí)行流程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中回調(diào)函數(shù)?(callback)?及其實際應(yīng)用場景
在Java中回調(diào)函數(shù)(Callback)是一種常見的設(shè)計模式,用于實現(xiàn)異步操作或事件處理,這篇文章主要給大家介紹了關(guān)于Java中回調(diào)函數(shù)?(callback)?及其實際應(yīng)用場景的相關(guān)資料,需要的朋友可以參考下2024-02-02
Gradle在國內(nèi)配置鏡像加速的實現(xiàn)步驟
在國內(nèi)使用 Gradle 構(gòu)建項目時,最大的痛點就是 依賴下載賊慢,甚至卡死,下面教你如何 配置國內(nèi)鏡像加速 Gradle 下載依賴,主要是通過改寫 repositories 中的源地址來實現(xiàn),親測有效,需要的朋友可以參考下2025-05-05
SpringBoot集成Devtools實現(xiàn)熱更新
DevTools是開發(fā)者工具集,主要用于簡化開發(fā)過程中的熱部署問題,熱部署是指在開發(fā)過程中,當(dāng)代碼發(fā)生變化時,無需手動重啟應(yīng)用,系統(tǒng)能夠自動檢測并重新加載修改后的代碼,本文給大家介紹了SpringBoot集成Devtools實現(xiàn)熱更新,需要的朋友可以參考下2024-08-08
使用WebUploader實現(xiàn)上傳文件功能(一)
這篇文章主要為大家詳細(xì)介紹了使用WebUploader實現(xiàn)上傳文件功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01

