目錄
前言
啟動流程概覽
一、第一階段:初始化SpringApplication
二、第二階段:運行SpringApplication
三、第三階段:環境準備
四、第四階段:創建應用上下文
五、第五階段:準備應用上下文
六、第六階段:刷新應用上下文(核心)
七、第七階段:啟動后處理
啟動流程圖解
Spring Boot啟動流程與自動裝配的聯系
總結
前言
????????Spring Boot以其"開箱即用"的特性大大簡化了Spring應用的開發部署流程。只需一個main方法和一個簡單的SpringApplication.run()
調用,我們的應用就能快速啟動。但這背后究竟發生了什么?本文將深入剖析Spring Boot應用的完整啟動流程,帶你理解從點擊"運行"到應用完全就緒的每一個關鍵步驟。
啟動流程概覽
Spring Boot的啟動過程可以概括為以下幾個核心階段:
-
初始化SpringApplication實例
-
運行SpringApplication
-
準備環境設置
-
創建應用上下文
-
刷新應用上下文(核心)
-
執行Runner接口實現
下面我們詳細分析每個階段的具體工作。
一、第一階段:初始化SpringApplication
????????當我們調用SpringApplication.run(Application.class, args)
時,首先會初始化一個SpringApplication實例
//代碼示例
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[] { primarySource }, args);
}public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);
}
在SpringApplication的構造函數中,會進行以下關鍵操作:
-
推斷應用類型:根據類路徑下的依賴判斷是SERVLET應用(Spring MVC)、REACTIVE應用(WebFlux)還是普通應用
-
加載應用上下文初始化器:通過SpringFactoriesLoader從META-INF/spring.factories加載ApplicationContextInitializer
-
加載應用監聽器:同樣通過SpringFactoriesLoader加載ApplicationListener
-
推斷主配置類:根據堆棧信息找到包含main方法的類
二、第二階段:運行SpringApplication
run方法是整個啟動流程的核心:
public ConfigurableApplicationContext run(String... args) {// 1. 創建啟動計時器StopWatch stopWatch = new StopWatch();stopWatch.start();// 2. 初始化默認應用上下文ConfigurableApplicationContext context = null;// 3. 配置headless屬性configureHeadlessProperty();// 4. 獲取SpringApplicationRunListenersSpringApplicationRunListeners listeners = getRunListeners(args);// 5. 發布應用開始啟動事件listeners.starting();try {// 6. 準備環境ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 7. 打印BannerBanner printedBanner = printBanner(environment);// 8. 創建應用上下文context = createApplicationContext();// 9. 準備應用上下文prepareContext(context, environment, listeners, applicationArguments, printedBanner);// 10. 刷新應用上下文(核心步驟)refreshContext(context);// 11. 上下文刷新后處理afterRefresh(context, applicationArguments);// 12. 停止計時器stopWatch.stop();// 13. 發布應用啟動完成事件if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}listeners.started(context);// 14. 調用ApplicationRunner和CommandLineRunnercallRunners(context, applicationArguments);} catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {listeners.running(context);} catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;
}
三、第三階段:環境準備
prepareEnvironment()
方法負責準備應用運行環境:
-
創建環境對象:根據應用類型創建StandardEnvironment或StandardServletEnvironment
-
配置環境:配置PropertySources和Profiles
-
發布環境準備事件:通過EnvironmentPostProcessorApplicationListener處理
-
綁定環境到SpringApplication
-
轉換配置:將命令行參數轉換為PropertySource
-
處理ConfigurationProperties:驗證和綁定@ConfigurationProperties
四、第四階段:創建應用上下文
createApplicationContext()
根據應用類型創建對應的應用上下文:
-
Servlet應用:AnnotationConfigServletWebServerApplicationContext
-
Reactive應用:AnnotationConfigReactiveWebServerApplicationContext
-
普通應用:AnnotationConfigApplicationContext
五、第五階段:準備應用上下文
prepareContext()
方法準備創建好的應用上下文:
-
設置環境
-
后處理上下文:調用ApplicationContextInitializer
-
發布上下文準備事件
-
注冊SpringBootBanner
-
設置資源加載器和類加載器
-
注冊Bean定義:
-
注冊主配置類(@SpringBootApplication標注的類)
-
注冊命令行參數Bean
-
注冊Banner Bean
-
六、第六階段:刷新應用上下文(核心)
refreshContext()
調用的是AbstractApplicationContext的refresh()方法,這是Spring容器的核心生命周期方法:
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 1. 準備刷新上下文prepareRefresh();// 2. 獲取刷新后的BeanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 3. 準備BeanFactory使用上下文prepareBeanFactory(beanFactory);try {// 4. 允許BeanFactory的后處理postProcessBeanFactory(beanFactory);// 5. 調用BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactory);// 6. 注冊BeanPostProcessorregisterBeanPostProcessors(beanFactory);// 7. 初始化MessageSourceinitMessageSource();// 8. 初始化事件廣播器initApplicationEventMulticaster();// 9. 初始化特殊Bean(由子類實現)onRefresh();// 10. 注冊監聽器registerListeners();// 11. 完成BeanFactory初始化,實例化所有非懶加載單例finishBeanFactoryInitialization(beanFactory);// 12. 完成刷新,發布上下文刷新事件finishRefresh();} catch (BeansException ex) {// 13. 銷毀已創建的單例BeandestroyBeans();// 14. 重置激活標志cancelRefresh(ex);throw ex;} finally {// 15. 重置Spring核心中的公共內省緩存resetCommonCaches();}}
}
對于Spring Boot來說,onRefresh()
方法尤為重要,這里會創建嵌入式Web服務器:
protected void onRefresh() {super.onRefresh();try {createWebServer(); // 創建Tomcat、Jetty或Undertow服務器} catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);}
}
七、第七階段:啟動后處理
刷新完成后,Spring Boot會執行一些后處理操作:
-
調用ApplicationRunner和CommandLineRunner:執行應用中定義的Runner實現
-
發布應用就緒事件:ApplicationReadyEvent,表示應用已完全啟動
-
啟動完成:此時應用已完全就緒,可以處理請求
啟動流程圖解
Spring Boot啟動流程與自動裝配的聯系
? ? ? ? 1.核心關系:自動裝配是啟動流程的關鍵環節
????????簡單來說,自動裝配是Spring Boot啟動流程中的一個核心子過程。沒有啟動流程提供的環境、上下文和機制,自動裝配無法工作;而沒有自動裝配,Spring Boot的啟動就失去了"智能"和"自動化"的特性,退回到了傳統Spring應用的繁瑣配置模式。
????????2.自動裝配的具體執行時機
????????自動裝配發生在應用上下文刷新階段,具體在refreshContext()
方法中的invokeBeanFactoryPostProcessors(beanFactory)
步驟:
public void refresh() throws BeansException, IllegalStateException {// ... 前面的步驟invokeBeanFactoryPostProcessors(beanFactory); // 自動裝配在這里發生!// ... 后續步驟
}
總結
????????Spring Boot的啟動流程是一個精心設計的過程,它將傳統的XML配置轉換為基于Java的自動配置,通過條件化裝配和自動發現機制,極大地簡化了Spring應用的開發和部署。理解這個流程不僅有助于我們更好地使用Spring Boot,還能在遇到問題時快速定位和解決。
????????整個過程體現了Spring Boot的核心設計理念:約定優于配置、自動裝配和微內核架構。通過事件監聽機制和擴展點設計,Spring Boot在保持簡潔性的同時,也提供了極大的靈活性和可擴展性。