深入剖析Spring Boot應用啟動全流程

目錄

前言

啟動流程概覽

一、第一階段:初始化SpringApplication

二、第二階段:運行SpringApplication

三、第三階段:環境準備

四、第四階段:創建應用上下文

五、第五階段:準備應用上下文

六、第六階段:刷新應用上下文(核心)

七、第七階段:啟動后處理

啟動流程圖解

Spring Boot啟動流程與自動裝配的聯系

總結


前言

????????Spring Boot以其"開箱即用"的特性大大簡化了Spring應用的開發部署流程。只需一個main方法和一個簡單的SpringApplication.run()調用,我們的應用就能快速啟動。但這背后究竟發生了什么?本文將深入剖析Spring Boot應用的完整啟動流程,帶你理解從點擊"運行"到應用完全就緒的每一個關鍵步驟。


啟動流程概覽

Spring Boot的啟動過程可以概括為以下幾個核心階段:

  1. 初始化SpringApplication實例

  2. 運行SpringApplication

  3. 準備環境設置

  4. 創建應用上下文

  5. 刷新應用上下文(核心)

  6. 執行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的構造函數中,會進行以下關鍵操作:

  1. 推斷應用類型:根據類路徑下的依賴判斷是SERVLET應用(Spring MVC)、REACTIVE應用(WebFlux)還是普通應用

  2. 加載應用上下文初始化器:通過SpringFactoriesLoader從META-INF/spring.factories加載ApplicationContextInitializer

  3. 加載應用監聽器:同樣通過SpringFactoriesLoader加載ApplicationListener

  4. 推斷主配置類:根據堆棧信息找到包含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()方法負責準備應用運行環境:

  1. 創建環境對象:根據應用類型創建StandardEnvironment或StandardServletEnvironment

  2. 配置環境:配置PropertySources和Profiles

  3. 發布環境準備事件:通過EnvironmentPostProcessorApplicationListener處理

  4. 綁定環境到SpringApplication

  5. 轉換配置:將命令行參數轉換為PropertySource

  6. 處理ConfigurationProperties:驗證和綁定@ConfigurationProperties

四、第四階段:創建應用上下文

createApplicationContext()根據應用類型創建對應的應用上下文:

  • Servlet應用:AnnotationConfigServletWebServerApplicationContext

  • Reactive應用:AnnotationConfigReactiveWebServerApplicationContext

  • 普通應用:AnnotationConfigApplicationContext

五、第五階段:準備應用上下文

prepareContext()方法準備創建好的應用上下文:

  1. 設置環境

  2. 后處理上下文:調用ApplicationContextInitializer

  3. 發布上下文準備事件

  4. 注冊SpringBootBanner

  5. 設置資源加載器和類加載器

  6. 注冊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會執行一些后處理操作:

  1. 調用ApplicationRunner和CommandLineRunner:執行應用中定義的Runner實現

  2. 發布應用就緒事件:ApplicationReadyEvent,表示應用已完全啟動

  3. 啟動完成:此時應用已完全就緒,可以處理請求

啟動流程圖解

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在保持簡潔性的同時,也提供了極大的靈活性和可擴展性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94349.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94349.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94349.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Matplotlib 可視化大師系列(三):plt.bar() 與 plt.barh() - 清晰對比的柱狀圖

目錄Matplotlib 可視化大師系列博客總覽Matplotlib 可視化大師系列&#xff08;三&#xff09;&#xff1a;plt.bar() 與 plt.barh() - 清晰對比的柱狀圖一、 柱狀圖是什么&#xff1f;何時使用&#xff1f;二、 函數原型與核心參數plt.bar(x, height, ...) - 垂直柱狀圖plt.ba…

基于 FastAPI 和 OpenFeature 使用 Feature Flag 控制業務功能

模擬業務場景&#xff1a;多租戶系統跨域轉賬&#xff0c;需要控制某租戶下某用戶是否可以在某域轉賬 open_feature_util.py import typing from abc import abstractmethod, ABCMeta from typing import Sequencefrom openfeature.evaluation_context import EvaluationContex…

Stm32通過ESP8266 WiFi連接阿里云平臺

本文將介紹stm32如何通過WiFi來連接阿里云&#xff0c;上傳數據和接收指令。要先與阿里云建立TCP連接&#xff0c;然后再通過MQTT協議交互。 大體流程&#xff1a;1、在阿里云網頁上創建產品和設備&#xff1b;2、stm32通過WiFi連接云平臺&#xff1b;3、MQTT連接阿里云&#…

北京-測試-入職甲方金融-上班第三天

今日上班時間9-20.18&#xff0c;再加42分鐘就可以拿到75塊錢了&#xff0c;但我想回家&#xff0c;所以下班今天上午有人事舉辦的入職培訓&#xff0c;下午有業務培訓&#xff0c;培訓完領導給我安排了兩個需求。慌死&#xff0c;嚇死&#xff0c;我都不懂&#xff0c;業務和工…

Java基礎第2天總結

使用switch時注意事項&#xff1a;表達式類型只能是byte、short、int、char,JDK5開始支持枚舉&#xff0c;JDK7開始支持String&#xff0c;不支持double、float、long(精確度問題&#xff0c;小數有點不精確)。case給出的值不允許重復&#xff0c;且只能是字面量&#xff0c;不…

鴻蒙開發中的List組件詳解

目錄 引言 1.List組件基礎 2.List接口參數 1.space 2.initialIndex 3.scroller 3.ListView的屬性 1.listDirection 2.lanes 3.divider 4.scrollBar 4.布局與約束 5.ListItem生命周期 1.使用ForEach創建ListItem 2.使用LazyForEach創建ListItem 3…

2026界計算機專業畢業的有福了!(開題報告任務書)

開題報告 我們以基于Java的婚紗店管理系統為案例進行指導。 任務書&#xff1a; 首先是畢設的立題依據&#xff0c;這個主要描寫一些簡潔大體的大白話&#xff0c;描述一下你為什么要做這個題目的畢設。 那就需要你描述一下現階段社會面婚紗店的運營情況&#xff0c;寫一些…

安全、高效、可靠的物理隔離網絡安全專用設備———信刻光盤安全隔離與文件單向導入系統!

著各種數據傳輸、儲存技術、信息技術的快速發展&#xff0c;保護信息安全是重中之重。軍工企業、政府、部隊及企事業單位等利用A網與B網開展導入/導出相關工作已成為不可逆轉的趨勢。針對于業務需要與保密規范相關要求&#xff0c;涉及重要秘密信息&#xff0c;需做到完全的物理…

JetPack 與 PyTorch 版本對應及資源詳情

下載鏈接 JetPack 版本適配 PyTorch 版本發布日期可下載資源&#xff08;.whl 安裝包 / 文檔&#xff09;JP 6.1PyTorch 2.5.0a0&#xff08;構建號&#xff1a;872d972e41.nv24.08.17622132&#xff09;2024/10/01- torch-2.5.0a0872d972e41.nv24.08.17622132-cp310-cp310-li…

【c++進階系列】:萬字詳解多態

&#x1f525; 本文專欄&#xff1a;c &#x1f338;作者主頁&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客勵志語錄&#xff1a; 你以為自己在孤獨地爬坡嗎&#xff1f;看看身后吧——那些被汗水浸濕的腳印&#xff0c;早已連成一道向上的階梯 ★★★ 本文前置知識&am…

AI+預測3D新模型百十個定位預測+膽碼預測+去和尾2025年8月23日第168彈

從今天開始&#xff0c;咱們還是暫時基于舊的模型進行預測&#xff0c;好了&#xff0c;廢話不多說&#xff0c;按照老辦法&#xff0c;重點8-9碼定位&#xff0c;配合三膽下1或下2&#xff0c;殺1-2個和尾&#xff0c;再殺4-5個和值&#xff0c;可以做到100-300注左右。(1)定位…

分布式搜索(Elasticsearch)深入用法

目錄 數據聚合 聚合的種類 DSL實現聚合 桶聚合 度量聚合 RestAPI實現聚合 多條件聚合 自動補全 拼音分詞器 自定義分詞器 自動補全查詢 實現搜索框自動補全 數據同步 數據同步思路分析 實現elasticsearch與數據庫數據同步 集群 搭建ES集群 集群腦裂問題 集群…

java:接口與實現類

1. Java 基礎層面接口&#xff08;Interface&#xff09; 只是方法的定義/規范&#xff0c;里面沒有真正的邏輯。例如&#xff1a;public interface IBookService {boolean save(Book book); }&#x1f449; 這里只說明了&#xff1a;我要有一個 save 方法&#xff0c;但“怎么…

Chrome 插件開發實戰:從入門到進階

1.1 Chrome 插件的魅力與應用場景Chrome 插件是增強 Chrome 瀏覽器功能的得力助手&#xff0c;能實現廣告攔截、密碼管理、標簽管理等實用功能。在日常辦公中&#xff0c;我們可以借助插件提升效率&#xff0c;如自動填充表單、快速保存網頁內容&#xff1b;在瀏覽網頁時&#…

通過官方文檔詳解Ultralytics YOLO 開源工程-熟練使用 YOLO11實現分割、分類、旋轉框檢測和姿勢估計(附測試代碼)

目錄 前言&#xff1a; 1.了解ultralytics工程與yolo模型 1.1 yolo11可以為我們做些什 1.2 yolo11模型的高性能 1.3 對于yolo11一些常見的問題 1.3.1 YOLO11 如何以更少的參數實現更高的精度&#xff1f; 1.3.2 YOLO11 可以部署在邊緣設備上嗎&#xff1f; 2. 深入了解y…

vue實現小程序oss分片上傳

隨著小程序越來越普及,小程序上傳文件必不可少,那么上傳的文件大小就不可控了,小則幾mb,大到好幾百mb,小文件還可以,但是一到超過200mb或稍微再大些的小程序就很容易上傳失敗,導致功能不能繼續進行。以下我們就來解決這個問題,將大文件實現分片上傳 溫馨提示,不要看內…

14.Shell腳本修煉手冊--玩轉循環結構(While 與 Until 的應用技巧與案例)

while 循環和 until 循環的應用實踐 文章目錄while 循環和 until 循環的應用實踐當型和直到型循環&#xff1a;兩種 "重復" 的邏輯while 循環&#xff1a;滿足條件就繼續until 循環&#xff1a;不滿足條件就繼續基礎示例&#xff1a;從簡單場景學用法示例 1&#xff…

chromadb使用hugging face模型時利用鏡像網站下載注意事項

chromadb默認使用sentence-transformers/all-MiniLM-L6-v2的詞嵌入&#xff08;詞向量&#xff09;模型&#xff0c;如果在程序首次運行時&#xff0c;collection的add或query操作時如果沒有指定embeddings或query_embeddings&#xff0c;程序會自動下載相關嵌入向量模型&#…

基于大模型的對話式推薦系統技術架構設計

注&#xff1a;此文章內容均節選自充電了么創始人&#xff0c;CEO兼CTO陳敬雷老師的新書《GPT多模態大模型與AI Agent智能體》&#xff08;跟我一起學人工智能&#xff09;【陳敬雷編著】【清華大學出版社】 清華《GPT多模態大模型與AI Agent智能體》書籍配套視頻課程【陳敬雷…

第1章 React組件開發基礎

在掌握React開發之前,我們需要先建立扎實的組件開發基礎。這些基礎知識不僅影響你的開發效率,更決定了應用程序的性能、可維護性和團隊協作的順暢程度。 本章將深入探討React組件開發的核心技巧,從JSX語法優化到組件架構設計,幫你建立正確的React開發思維模式。 ??? 本…