Spring Boot 應(yīng)用程序啟動(dòng)時(shí)執(zhí)行完整流程(最新推薦)
關(guān)于Spring Boot 應(yīng)用程序啟動(dòng)時(shí) main 方法的完整執(zhí)行流程。我會(huì)按照方法調(diào)用的核心順序進(jìn)行描述,并解釋每個(gè)關(guān)鍵方法的作用。
核心流程總覽
在Spring Boot應(yīng)用中,我們通常會(huì)寫(xiě)一個(gè)包含main方法的類(lèi),并調(diào)用SpringApplication.run。
示例代碼:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
整個(gè)啟動(dòng)過(guò)程可以概括為:構(gòu)造 SpringApplication 對(duì)象 -> 執(zhí)行 run 方法 -> 啟動(dòng)內(nèi)嵌服務(wù)器 -> 完成應(yīng)用啟動(dòng)。
第一階段:SpringApplication實(shí)例化
執(zhí)行方法:new SpringApplication(primarySources)
執(zhí)行
this(null, primarySources):- 作用:調(diào)用內(nèi)部的構(gòu)造器。
- 最主要的部分是
WebApplicationType.deduceFromClasspath()方法:- 這個(gè)方法的作用是:根據(jù)類(lèi)路徑下存在的類(lèi)來(lái)推斷應(yīng)用類(lèi)型。
- 它會(huì)檢查
DispatcherHandler、DispatcherServlet、Servlet等類(lèi)的存在性,從而判斷應(yīng)用是REACTIVE(響應(yīng)式)、SERVLET(標(biāo)準(zhǔn)的 Servlet Web 應(yīng)用)還是NONE(非 Web 應(yīng)用)。我們最常見(jiàn)的 Spring MVC 應(yīng)用就是SERVLET類(lèi)型。
執(zhí)行
setInitializers方法:- 作用:設(shè)置應(yīng)用初始化器 (
ApplicationContextInitializer)。 - 最主要的部分是
getSpringFactoriesInstances(ApplicationContextInitializer.class)方法:- 這個(gè)方法的作用是:使用 Spring 工廠加載機(jī)制,從
META-INF/spring.factories配置文件中加載并實(shí)例化所有配置的ApplicationContextInitializer實(shí)現(xiàn)類(lèi)。 - 常見(jiàn)的初始化器如
ConfigurationWarningsApplicationContextInitializer(檢查配置警告)、ContextIdApplicationContextInitializer(設(shè)置上下文 ID)等。這些初始化器會(huì)在ApplicationContext刷新之前被調(diào)用。
- 這個(gè)方法的作用是:使用 Spring 工廠加載機(jī)制,從
- 作用:設(shè)置應(yīng)用初始化器 (
執(zhí)行
setListeners方法:- 作用:設(shè)置應(yīng)用監(jiān)聽(tīng)器 (
ApplicationListener)。 - 最主要的部分同樣是
getSpringFactoriesInstances(ApplicationListener.class)方法:- 這個(gè)方法的作用是:從
spring.factories中加載并實(shí)例化所有配置的ApplicationListener。 - 這些監(jiān)聽(tīng)器用于監(jiān)聽(tīng)在應(yīng)用啟動(dòng)過(guò)程中發(fā)布的各類(lèi)事件,例如
ApplicationStartedEvent、ApplicationReadyEvent等。ClearCachesApplicationListener(清除緩存)、FileEncodingApplicationListener(檢查文件編碼)都是常見(jiàn)的監(jiān)聽(tīng)器。
- 這個(gè)方法的作用是:從
- 作用:設(shè)置應(yīng)用監(jiān)聽(tīng)器 (
執(zhí)行
deduceMainApplicationClass方法:- 作用:推導(dǎo)出主應(yīng)用程序類(lèi)(即我們寫(xiě)了
main方法的那個(gè)類(lèi))。 - 原理是:遍歷當(dāng)前調(diào)用棧,找到第一個(gè)方法名為
main的類(lèi)。
- 作用:推導(dǎo)出主應(yīng)用程序類(lèi)(即我們寫(xiě)了
至此,SpringApplication 對(duì)象構(gòu)造完畢,它已經(jīng)準(zhǔn)備好了初始化器和監(jiān)聽(tīng)器。
第二階段:執(zhí)行run方法
執(zhí)行方法:SpringApplication.run(primarySources, args)
這是整個(gè)啟動(dòng)流程最核心、最復(fù)雜的方法。
執(zhí)行
getRunListeners方法并調(diào)用listeners.starting():- 作用:獲取
SpringApplicationRunListeners并發(fā)布ApplicationStartingEvent事件。 - 說(shuō)明:
SpringApplicationRunListeners是SpringApplicationRunListener的集合,它專(zhuān)門(mén)用于監(jiān)聽(tīng)SpringApplication的run方法執(zhí)行過(guò)程中的關(guān)鍵節(jié)點(diǎn)。第一步就是發(fā)布應(yīng)用正在啟動(dòng)的事件。
- 作用:獲取
執(zhí)行
prepareEnvironment方法:- 作用:準(zhǔn)備和應(yīng)用環(huán)境 (
Environment),這是整個(gè)應(yīng)用配置的基礎(chǔ)。 - 最主要的部分是:
getOrCreateEnvironment():根據(jù)應(yīng)用類(lèi)型創(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事件。這是一個(gè)極其重要的擴(kuò)展點(diǎn),監(jiān)聽(tīng)這個(gè)事件的監(jiān)聽(tīng)器(最著名的是ConfigFileApplicationListener)會(huì)從application.properties、application.yml等文件中加載我們自定義的配置屬性。
- 作用:準(zhǔn)備和應(yīng)用環(huán)境 (
執(zhí)行
printBanner方法:- 作用:在控制臺(tái)打印 Spring Boot 的 Banner。
執(zhí)行
createApplicationContext方法:- 作用:創(chuàng)建
ApplicationContext(IoC 容器)。 - 根據(jù)第一步推斷出的
WebApplicationType,創(chuàng)建不同類(lèi)型的上下文。對(duì)于 Servlet Web 應(yīng)用,會(huì)創(chuàng)建AnnotationConfigServletWebServerApplicationContext。
- 作用:創(chuàng)建
執(zhí)行
prepareContext方法:- 作用:準(zhǔn)備上面創(chuàng)建好的
ApplicationContext。 - 最主要的部分是:
postProcessApplicationContext(context):后處理應(yīng)用上下文,例如設(shè)置 Bean 名稱(chēng)生成器、資源加載器。applyInitializers(context):應(yīng)用初始化器。調(diào)用在第一步中加載的所有ApplicationContextInitializer的initialize方法,允許我們?cè)谌萜魉⑿虑皩?duì)上下文進(jìn)行自定義。listeners.contextPrepared(context):發(fā)布ApplicationContextInitializedEvent事件,通知監(jiān)聽(tīng)器上下文已準(zhǔn)備就緒。load(context, sources.toArray(new Object[0])):將主源(即我們的@SpringBootApplication注解類(lèi))加載到上下文中,為后續(xù)的組件掃描和 Bean 定義注冊(cè)做準(zhǔn)備。listeners.contextLoaded(context):發(fā)布ApplicationPreparedEvent事件,通知監(jiān)聽(tīng)器上下文已加載完畢。
- 作用:準(zhǔn)備上面創(chuàng)建好的
第三階段:刷新應(yīng)用上下文 (最最核心)
執(zhí)行方法:refreshContext(context)
這個(gè)方法內(nèi)部會(huì)調(diào)用 AbstractApplicationContext.refresh(),這是 Spring 框架容器初始化的標(biāo)準(zhǔn)流程。
執(zhí)行
prepareRefresh()方法:- 作用:刷新前的準(zhǔn)備工作,例如初始化屬性源、驗(yàn)證必要的屬性。
執(zhí)行
obtainFreshBeanFactory()方法:- 作用:獲取或刷新內(nèi)部的
BeanFactory(DefaultListableBeanFactory)。BeanFactory是 Spring 容器的基礎(chǔ)。
- 作用:獲取或刷新內(nèi)部的
執(zhí)行
prepareBeanFactory(beanFactory)方法:- 作用:準(zhǔn)備
BeanFactory,配置它的類(lèi)加載器、后置處理器等標(biāo)準(zhǔn)配置。
- 作用:準(zhǔn)備
執(zhí)行
postProcessBeanFactory(beanFactory)方法:- 作用:允許在 Bean 定義加載完成后、實(shí)例化之前,對(duì)
BeanFactory進(jìn)行后處理。這是一個(gè)空方法,供子類(lèi)擴(kuò)展。
- 作用:允許在 Bean 定義加載完成后、實(shí)例化之前,對(duì)
執(zhí)行
invokeBeanFactoryPostProcessors(beanFactory)方法:- 作用:這是 Spring Boot 自動(dòng)配置的魔法入口!
- 最主要的部分是:調(diào)用所有
BeanFactoryPostProcessor。 - 其中,
ConfigurationClassPostProcessor會(huì)解析@Configuration注解的類(lèi)。它會(huì)發(fā)現(xiàn)我們的主類(lèi)上的@SpringBootApplication注解。 @SpringBootApplication中包含@EnableAutoConfiguration,后者會(huì)導(dǎo)入AutoConfigurationImportSelector。AutoConfigurationImportSelector會(huì)從META-INF/spring.factories中加載所有EnableAutoConfiguration鍵對(duì)應(yīng)的自動(dòng)配置類(lèi)(如DataSourceAutoConfiguration,WebMvcAutoConfiguration)。- 這些自動(dòng)配置類(lèi)根據(jù)條件(如類(lèi)路徑下是否存在某個(gè)類(lèi)、是否設(shè)置了某個(gè)屬性等)決定是否生效,并向容器中批量添加 Bean 定義。
執(zhí)行
registerBeanPostProcessors(beanFactory)方法:- 作用:注冊(cè)
BeanPostProcessor。這些處理器會(huì)在 Bean 實(shí)例化之后、初始化前后 被調(diào)用,用于對(duì) Bean 進(jìn)行增強(qiáng)(如@Autowired,@PostConstruct等功能都是通過(guò)BeanPostProcessor實(shí)現(xiàn)的)。
- 作用:注冊(cè)
執(zhí)行
initMessageSource()方法:- 作用:初始化國(guó)際化相關(guān)的消息源。
執(zhí)行
initApplicationEventMulticaster()方法:- 作用:初始化應(yīng)用事件廣播器,用于事件發(fā)布。
執(zhí)行
onRefresh()方法:- 作用:這是 Spring Boot 創(chuàng)建并啟動(dòng)內(nèi)嵌 Web 服務(wù)器的關(guān)鍵步驟!
- 在
ServletWebServerApplicationContext中,此方法被重寫(xiě)。 - 最主要的部分是
createWebServer()方法:- 這個(gè)方法的作用是:從
BeanFactory中獲取ServletWebServerFactory(如TomcatServletWebServerFactory)。 - 調(diào)用
factory.getWebServer(...)方法,這會(huì)創(chuàng)建內(nèi)嵌的 Tomcat/Jetty/Undertow 服務(wù)器實(shí)例,并初始化 Servlet 容器(初始化DispatcherServlet并注冊(cè)到容器中)。此時(shí),Web 服務(wù)器已經(jīng)創(chuàng)建好,但尚未開(kāi)始監(jiān)聽(tīng)端口。
- 這個(gè)方法的作用是:從
執(zhí)行
registerListeners()方法:- 作用:注冊(cè)監(jiān)聽(tīng)器,將事件監(jiān)聽(tīng)器注冊(cè)到第 8 步初始化的事件廣播器中。
執(zhí)行
finishBeanFactoryInitialization(beanFactory)方法:- 作用:完成
BeanFactory的初始化,實(shí)例化所有剩余的非懶加載單例 Bean。 - 這是 IoC 容器依賴(lài)注入發(fā)生的主要階段。我們的 Controller、Service、Repository 等組件都在這個(gè)階段被創(chuàng)建和裝配。
- 作用:完成
執(zhí)行
finishRefresh()方法:- 作用:完成上下文的刷新工作,發(fā)布最終事件。
- 最主要的部分是:
publishEvent(new ContextRefreshedEvent(this)):發(fā)布ContextRefreshedEvent事件。- 在
ServletWebServerApplicationContext中,還會(huì)調(diào)用finishRefresh()的一個(gè)擴(kuò)展,最終啟動(dòng)內(nèi)嵌的 Web 服務(wù)器(例如TomcatWebServer.start()),開(kāi)始監(jiān)聽(tīng)指定的端口。至此,我們的應(yīng)用已經(jīng)可以處理 HTTP 請(qǐng)求了。
第四階段:?jiǎn)?dòng)后處理
- 執(zhí)行
afterRefresh(context, applicationArguments)方法:- 作用:刷新后處理,默認(rèn)為空。是一個(gè)擴(kuò)展點(diǎn)。
- 執(zhí)行
listeners.started(context)方法:- 作用:發(fā)布
ApplicationStartedEvent事件,通知所有監(jiān)聽(tīng)器應(yīng)用已啟動(dòng)。
- 作用:發(fā)布
- 執(zhí)行
callRunners(applicationArguments)方法:- 作用:調(diào)用
ApplicationRunner和CommandLineRunner接口的實(shí)現(xiàn)類(lèi)。 - 這是開(kāi)發(fā)者可以在應(yīng)用啟動(dòng)后、開(kāi)始接收流量前,執(zhí)行一些特定初始化邏輯的常用方式。
- 作用:調(diào)用
- 執(zhí)行
listeners.ready(context, timeTaken)方法:- 作用:發(fā)布
ApplicationReadyEvent事件。這個(gè)事件標(biāo)志著應(yīng)用已完全啟動(dòng)完畢,處于就緒狀態(tài)。它與ApplicationStartedEvent的區(qū)別在于,此時(shí)所有 Bean 都已初始化,內(nèi)嵌服務(wù)器已在運(yùn)行。 - 返回
ApplicationContext: - 作用:將已經(jīng)完全初始化好的
ApplicationContext返回。
- 作用:發(fā)布
總結(jié)
整個(gè)流程從 main 方法開(kāi)始,經(jīng)歷了 環(huán)境準(zhǔn)備 -> 容器創(chuàng)建 -> Bean定義加載(自動(dòng)配置) -> Bean實(shí)例化(依賴(lài)注入) -> 內(nèi)嵌服務(wù)器啟動(dòng) -> 運(yùn)行自定義初始化邏輯 等一系列復(fù)雜而精密的步驟,最終將一個(gè)功能完備的 Spring Boot 應(yīng)用呈現(xiàn)在我們面前。其中 refreshContext() 是整個(gè)流程的心臟,而自動(dòng)配置和內(nèi)嵌服務(wù)器是 Spring Boot 兩大核心特性的實(shí)現(xiàn)關(guān)鍵。
到此這篇關(guān)于Spring Boot 應(yīng)用程序啟動(dòng)時(shí)執(zhí)行流程的文章就介紹到這了,更多相關(guān)Spring Boot 啟動(dòng)時(shí)執(zhí)行流程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot監(jiān)聽(tīng)?wèi)?yīng)用程序啟動(dòng)的生命周期事件的四種方法
- SpringBoot應(yīng)用程序啟動(dòng)監(jiān)聽(tīng)功能的常見(jiàn)方法
- JAVA系統(tǒng)中Spring?Boot應(yīng)用程序的配置文件application.yml使用詳解
- Spring Boot應(yīng)用程序同時(shí)支持HTTP和HTTPS協(xié)議的實(shí)現(xiàn)方法
- 在Spring Boot應(yīng)用程序中使用Apache Kafka的方法步驟詳解
- Spring Boot Web應(yīng)用程序配置詳解
相關(guān)文章
詳解spring項(xiàng)目中如何動(dòng)態(tài)刷新bean
這篇文章主要為大家介紹了詳解spring項(xiàng)目中如何動(dòng)態(tài)刷新bean,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
springboot 配置文件配置項(xiàng)前綴為0的數(shù)字特殊處理方式
這篇文章主要介紹了springboot 配置文件配置項(xiàng)前綴為0的數(shù)字特殊處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
一文詳解Spring Aop @After(后置通知)的使用場(chǎng)景
@After 是 Spring AOP 中的另一種通知(Advice)類(lèi)型,通常被稱(chēng)為“后置通知”或“最終通知”,本文將通過(guò)詳細(xì)的代碼示例給大家介紹一下Spring Aop @After(后置通知)的使用場(chǎng)景,需要的朋友可以參考下2025-06-06
教你Springboot如何實(shí)現(xiàn)圖片上傳
這篇文章主要介紹了教你Springboot如何實(shí)現(xiàn)圖片上傳,首先大家明白圖片上傳,需要在數(shù)據(jù)庫(kù)定義一個(gè)varchar類(lèi)型的img字段圖片字段,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
springboot訪(fǎng)問(wèn)靜態(tài)資源遇到的坑及解決
這篇文章主要介紹了springboot訪(fǎng)問(wèn)靜態(tài)資源遇到的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Maven打包jar生成javadoc文件和source文件代碼實(shí)例
這篇文章主要介紹了Maven打包jar生成javadoc文件和source文件代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Java中使用@CrossOrigin和Proxy解決跨域問(wèn)題詳解
這篇文章主要介紹了Java中使用@CrossOrigin和Proxy解決跨域問(wèn)題詳解,在Web開(kāi)發(fā)中,如果前端頁(yè)面和后端接口不在同一個(gè)域名下,就會(huì)發(fā)生跨域請(qǐng)求的問(wèn)題,同源策略是瀏覽器的一種安全策略,它限制了來(lái)自不同源的客戶(hù)端腳本在瀏覽器中運(yùn)行時(shí)的交互,需要的朋友可以參考下2023-12-12
SpringBoot集成canal實(shí)現(xiàn)示例解析
這篇文章主要為大家介紹了springboot整合canal的示例實(shí)現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多多進(jìn)步,早日升職加薪2022-02-02

