SpringBoot啟動項目詳解

SpringBoot 的啟動過程是一個整合 Spring 核心容器、自動配置、嵌入式服務器等功能的復雜流程,核心目標是 “簡化配置、快速啟動”。下面從入口類開始,逐步拆解其詳細啟動步驟:

一、啟動入口:@SpringBootApplicationmain方法

SpringBoot 應用的啟動入口是一個帶有@SpringBootApplication注解的類,其中的main方法是程序的起點:

@SpringBootApplication
public class MyApplication {public static void main(String[] args) {// 核心啟動方法SpringApplication.run(MyApplication.class, args);}
}

這行代碼看似簡單,卻包含了初始化 Spring 容器、觸發自動配置、啟動嵌入式服務器等一系列操作。

二、@SpringBootApplication注解的核心作用

@SpringBootApplication是一個 “復合注解”,它整合了三個關鍵注解,為啟動過程奠定基礎:

  1. @SpringBootConfiguration:本質是@Configuration,標識當前類是一個配置類,允許通過@Bean定義 Bean。
  2. @ComponentScan:自動掃描當前類所在包及其子包下的@Component(包括@Service@Controller等)注解類,將其注冊為 Spring Bean。
  3. @EnableAutoConfiguration:SpringBoot 的 “靈魂”,開啟自動配置功能,通過加載預設的配置類,自動配置 DataSource、Web 服務器等組件。

三、SpringApplication.run()的詳細流程

SpringApplication.run(MyApplication.class, args)是啟動的核心方法,可拆解為兩大階段SpringApplication實例初始化 +?run()方法執行。

階段 1:SpringApplication實例初始化(準備工作)

當調用SpringApplication.run(...)時,首先會創建SpringApplication實例,完成一系列初始化操作:

// 簡化的初始化邏輯
public SpringApplication(Class<?>... primarySources) {this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 1. 推斷應用類型(Servlet/Reactive/Native)this.webApplicationType = WebApplicationType.deduceFromClasspath();// 2. 加載初始化器(ApplicationContextInitializer)setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 3. 加載監聽器(ApplicationListener)setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 4. 推斷main方法所在的主類this.mainApplicationClass = deduceMainApplicationClass();
}

關鍵操作解析:

  • 推斷應用類型:通過類路徑中是否存在ServletReactive相關類,判斷是傳統 Web 應用(SERVLET)、響應式 Web 應用(REACTIVE)還是非 Web 應用(NONE)。
  • 加載初始化器:從META-INF/spring.factories文件中讀取ApplicationContextInitializer實現類(用于初始化 Spring 上下文)。
  • 加載監聽器:同樣從spring.factories中讀取ApplicationListener實現類(用于監聽啟動過程中的事件,如環境準備完成、容器刷新等)。
階段 2:run()方法執行(核心啟動流程)

run()方法是啟動的核心,包含 12 個關鍵步驟,按順序執行如下:

步驟 1:啟動計時器(記錄啟動時間)
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 開始計時

用于統計應用啟動總耗時,最終會在控制臺輸出(如Started MyApplication in 2.345 seconds)。

步驟 2:初始化運行監聽器(SpringApplicationRunListeners

通過SpringFactoriesLoader加載SpringApplicationRunListener實現類(默認是EventPublishingRunListener),用于在啟動各階段發布事件(如ApplicationStartingEventApplicationEnvironmentPreparedEvent等),觸發對應監聽器的邏輯。

步驟 3:準備環境(Environment

創建并配置Environment(環境對象),包含:

  • 系統環境變量、JVM 參數、命令行參數(args)。
  • 配置文件(application.properties/application.yml)中的屬性。
  • 激活的profiles(如dev/test/prod)。

過程:

  1. 為不同應用類型(Servlet/Reactive)創建對應Environment實例(如StandardServletEnvironment)。
  2. 加載配置文件:默認從classpath:classpath:/config/file:./file:./config/等路徑讀取。
  3. 處理命令行參數:將args中的參數(如--server.port=8081)添加到環境中,優先級最高。
步驟 4:打印 Banner(啟動圖標)

默認會在控制臺打印 SpringBoot 的 Banner 圖標(可通過spring.banner.location自定義,或設置spring.main.banner-mode=off關閉)。

步驟 5:創建ApplicationContext(Spring 容器)

根據應用類型創建對應的ApplicationContext(Spring 核心容器):

  • Servlet 應用AnnotationConfigServletWebServerApplicationContext
  • Reactive 應用AnnotationConfigReactiveWebServerApplicationContext
  • 非 Web 應用AnnotationConfigApplicationContext

ApplicationContext是 Spring 的 “大腦”,負責管理 Bean 的生命周期、依賴注入等核心功能。

步驟 6:準備ApplicationContext(上下文預處理)

為容器設置環境、注冊 Bean、應用初始化器等:

  1. 將步驟 3 中準備好的Environment設置到容器中。
  2. 調用所有ApplicationContextInitializerinitialize()方法,對容器進行自定義初始化(如添加屬性源、修改配置等)。
  3. 發布ApplicationContextInitializedEvent事件,通知監聽器容器已初始化。
  4. 注冊主配置類:將@SpringBootApplication標注的類(如MyApplication)注冊為 Spring 的配置類。
步驟 7:刷新ApplicationContext(容器核心初始化)

這是 Spring 容器的核心步驟(繼承自 Spring 的AbstractApplicationContext),包含 Bean 的掃描、加載、實例化等關鍵操作,具體包括:

7.1 執行BeanFactory的前置處理

初始化容器的BeanFactory(如DefaultListableBeanFactory),用于管理 BeanDefinition(Bean 的元數據)。

7.2 執行BeanFactoryPostProcessor(Bean 工廠后置處理器)

最關鍵的是自動配置類的加載
@EnableAutoConfiguration通過@Import(AutoConfigurationImportSelector.class)導入自動配置類。AutoConfigurationImportSelector會從META-INF/spring.factories中讀取EnableAutoConfiguration對應的配置類(如DataSourceAutoConfigurationWebMvcAutoConfiguration等),并根據@Conditional條件注解(如@ConditionalOnClass@ConditionalOnMissingBean)篩選出符合當前環境的配置類,注冊為 BeanDefinition。

7.3 注冊BeanPostProcessor(Bean 后置處理器)

用于在 Bean 實例化前后進行增強(如 AOP 代理、依賴注入等)。

7.4 初始化消息源(國際化支持)
7.5 初始化事件多播器(用于事件發布)
7.6 初始化容器特定 Bean(子類擴展點)

對 Web 應用而言,這里會觸發嵌入式服務器的創建與啟動
ServletWebServerApplicationContextonRefresh()方法中調用createWebServer(),根據類路徑中的依賴(如spring-boot-starter-tomcat)創建對應的服務器(Tomcat/Undertow/Jetty),并綁定端口(默認 8080)。

7.7 注冊監聽器到容器
7.8 完成 BeanFactory 初始化(實例化所有非懶加載單例 Bean)

容器會遍歷所有 BeanDefinition,實例化單例 Bean(@Lazy標注的除外),并執行依賴注入(@Autowired)、初始化方法(@PostConstructInitializingBean)等。

7.9 發布容器刷新完成事件(ContextRefreshedEvent
步驟 8:刷新后的操作
  • 清除緩存(如類加載緩存)。
  • 發布ApplicationStartedEvent事件(通知容器已刷新完成)。
步驟 9:執行Runner(自定義啟動邏輯)

調用所有ApplicationRunnerCommandLineRunnerrun()方法,執行啟動后的自定義邏輯(如加載初始數據、檢查配置等):

  • ApplicationRunner:接收ApplicationArguments參數(解析后的命令行參數)。
  • CommandLineRunner:直接接收原始String[] args參數。
步驟 10:發布啟動完成事件

發布ApplicationReadyEvent事件,通知應用已完全啟動,可對外提供服務。

步驟 11:停止計時器
stopWatch.stop(); // 停止計時
步驟 12:輸出啟動日志

打印啟動成功日志,包含總耗時、活躍 Profiles 等信息(如Started MyApplication in 2.345 seconds (JVM running for 3.123))。

四、核心機制總結

  1. 自動配置:通過@EnableAutoConfigurationspring.factories中的配置類,根據依賴和環境自動配置組件(如 DataSource、Web 服務器)。
  2. 嵌入式服務器:在容器刷新階段自動創建并啟動(如 Tomcat),無需手動部署到外部服務器。
  3. 事件驅動:通過SpringApplicationRunListenerApplicationListener在啟動各階段發布事件,支持擴展(如自定義監聽器處理特定階段邏輯)。
  4. 簡化配置:默認掃描路徑、默認配置文件、默認 Bean 注冊,減少手動配置。

五、流程圖總結

main() → SpringApplication實例化 → run()↓
初始化監聽器 → 準備環境(配置+參數) → 打印Banner → 創建ApplicationContext↓
準備上下文(設置環境+注冊配置類) → 刷新上下文(核心)↓├─ 加載自動配置類 → 注冊BeanDefinition├─ 實例化單例Bean → 依賴注入└─ 啟動嵌入式服務器(如Tomcat)↓
執行Runner → 發布啟動完成事件 → 輸出啟動日志

通過這一系列流程,SpringBoot 實現了 “零配置(或極簡配置)” 的快速啟動,讓開發者專注于業務邏輯而非框架配置。

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

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

相關文章

PCB 控深槽如何破解 5G 基站 120℃高熱魔咒?

5G 基站在高頻通信下的功耗較 4G 基站提升 3-4 倍&#xff0c;射頻模塊、電源單元等核心部件的工作溫度常突破 120℃&#xff0c;遠超設備安全閾值&#xff08;≤85℃&#xff09;&#xff0c;形成制約通信穩定性的 “高熱魔咒”。印制線路板&#xff08;PCB&#xff09;作為熱…

NEXT.js 打包部署到服務器

在網上查了一下&#xff0c;記錄一下1.首先執行打包命令&#xff0c;我這個項目是用的pnpm&#xff0c;可以根據項目需求使用 npm 或者別的pnpm run build2.打包完成后會有一個 .next 的文件夾&#xff0c;需要把下圖的這些文件放到服務器。服務器需要有node環境之后就需要執行…

【AI分析】uv庫自動安裝腳本uv-installer-0.8.3.ps1分析

目錄uv 安裝腳本完整分析報告1. 腳本概述2. 參數解析3. 環境變量控制4. 核心函數詳解a. Install-Binary&#xff08;主控函數&#xff09;b. Get-TargetTriple&#xff08;架構檢測&#xff09;c. Download&#xff08;下載處理&#xff09;d. Invoke-Installer&#xff08;安裝…

etcd 的安裝與使用

介紹 Etcd 是一個 golang 編寫的分布式、高可用的一致性鍵值存儲系統&#xff0c;用于配置共享和服 務發現等。它使用 Raft 一致性算法來保持集群數據的一致性&#xff0c;且客戶端通過長連接 watch 功能&#xff0c;能夠及時收到數據變化通知&#xff0c;相較于 Zookeeper 框…

conda : 無法將“conda”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱。請檢查名稱的拼寫,如果包括路徑,請確保路徑正

詳細問題 PS C:\Users\wh109> conda init powershell conda : 無法將“conda”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱。請檢查名稱的拼寫&#xff0c;如果包括路徑&#xff0c;請確保路徑正 確&#xff0c;然后再試一次。 所在位置 行:1 字符: 1conda init pow…

HQChart實戰教程58:K線主圖仿TradingView實現

本文將詳細介紹如何使用HQChart實現類似TradingView風格的K線主圖,包含完整的代碼實現和詳細注釋,適合金融圖表開發者和量化交易愛好者閱讀。 一、TradingView風格特點分析 在開始實現前,我們先分析TradingView的K線主圖核心特點: 簡潔現代的UI設計:深色背景、清晰的網格…

GitPython08-源碼解讀

GitPython08-源碼解讀 1-核心知識 1&#xff09;gitPython核心代碼很多都是對git命令返回的結果進行解析&#xff0c;在此補充git命令的返回內容2&#xff09;git ls-tree -> 查看某個提交或分支所對應的目錄樹3&#xff09;源碼中Tree對應的業務邏輯 -> 獲取git ls-tre…

中科院開源HYPIR圖像復原大模型:1.7秒,老照片變8K畫質

目錄 前言 一、告別“龜速”藝術家&#xff0c;擁抱“閃電”打印機 二、不止是高清&#xff1a;它看得懂文字&#xff0c;更能理解你的心意 2.1 首先&#xff0c;它是位“文字保衛者” 2.2 其次&#xff0c;它還是個“細節創造家” 2.3 最后&#xff0c;它是一個能“聽懂…

設計Mock華為昇騰GPU的MindSpore和CANN的庫的流程與實現

在沒有華為昇騰GPU可用的情況下用C庫寫一個Mock MindSpore和CANN的庫&#xff0c;調用多核CPU和內存的資源來模擬GPU的算力&#xff0c;調試MindSpore和CANN的C代碼&#xff0c;做這個庫的基本流程步驟和詳細設計是什么&#xff1f; 要創建一個Mock庫來模擬華為昇騰GPU&#xf…

【AI問答記錄】grafana接收query請求中未攜帶step參數,后端基于intervalMs和maxDataPoints等參數計算step的邏輯

讓我詳細分析Grafana源碼中計算step的完整邏輯&#xff0c;它確實比簡單的intervalMs/1000復雜得多。 完整的Step計算流程 1. 入口點&#xff1a;[models.Parse](file://F:\JavaProject\grafana-release-11.2.0\pkg\promlib\models\query.go#L190-L274)函數 在pkg/promlib/mode…

再談亞馬遜云科技(AWS)上海AI研究院7月22日關閉事件

【科技明說 &#xff5c; 科技熱點關注】亞馬遜云科技&#xff08;AWS&#xff09;上海AI研究院已于2025年7月22日正式解散&#xff0c;這是亞馬遜在全球范圍內的最后一個海外研究中心的關閉。這個消息是否是真的&#xff0c;目前得到的印證來自其研發中心的首席科學家王敏捷在…

Python中的決策樹機器學習模型簡要介紹和代碼示例(基于sklearn)

一、決策樹定義 決策樹是一種監督學習算法&#xff0c;可用于**分類&#xff08;Classification&#xff09;和回歸&#xff08;Regression&#xff09;**任務。 它的結構類似樹狀結構&#xff1a; 內部節點&#xff1a;特征條件&#xff08;如X > 2&#xff09;葉子節點&am…

Redis集群分布式(Redis Cluster)底層實現原理詳細介紹

文章目錄一、Redis集群概念二、集群節點1. 節點如何啟動2. 節點的集群數據結構2.1 clusterNode結構2.2 clusterLink結構2.3 clusterState結構3. 節點如何加入集群三、數據分片機制1. 記錄節點的槽指派信息2. 傳播節點的槽指派信息3. 記錄集群所有槽的指派信息4. 節點的槽指派命…

【走遍美國精講筆記】第 1 課:林登大街 46 號

ACT 1-1 “我可以給您和您的小男孩拍張照嗎&#xff1f;” 【故事梗概】 自由攝影藝術家 Richard Stewart&#xff0c;正在為編出自己的影集《走遍美國》到處拍照。今天他在由紐約市曼哈頓區到斯塔滕島的渡船上工 作&#xff0c;回程中遇到了來自加州的一位黑人婦女 Martha Van…

Java中Lambda 表達式的解釋

從 Java 8 開始&#xff0c;Lambda 表達式成為 Java 的一等公民。它不僅讓代碼更簡潔&#xff0c;還為函數式編程打開了大門。如果你還沒真正理解或使用過 Lambda&#xff0c;這篇文章就是為你寫的。一、什么是 Lambda 表達式&#xff1f;Lambda 表達式是 Java 中的一種匿名函數…

Spring AI調用Embedding模型返回HTTP 400:Invalid HTTP request received分析處理

調用Embedding模型失敗 Spring AI項目使用的Embedding模型是公司平臺部署的&#xff0c;請求模型服務的時候報錯&#xff0c;返回了HTTP 400 - Invalid HTTP request received錯誤。然后換成云廠商在線Embedding模型地址&#xff0c;正常調通。我用Apifox直接調用公司的模型服務…

Pytorch-02數據集和數據加載器的基本原理和基本操作

1. 為什么要有數據集類和數據加載器類&#xff1f; 一萬個人會有一萬種獲取并處理原始數據樣本的代碼&#xff0c;這會導致對數據的操作代碼標準不一&#xff0c;并且很難復用。為了解決這個問題&#xff0c;Pytorch提供了兩種最基本的數據相關類&#xff1a; torch.utils.data…

無圖形界面的CentOS 7網絡如何配置

進入虛擬機輸入ip addr命令&#xff1a;從 ip addr命令的輸出可以明確看出 ??lo和 ens33是兩個不同的網絡接口&#xff08;網卡&#xff09;lo&#xff08;回環接口&#xff09;????作用??&#xff1a;虛擬的本地回環網卡&#xff0c;用于本機內部通信&#xff08;如 1…

機器學習之線性回歸的入門學習

線性回歸是一種監督學習算法&#xff0c;用于解決回歸問題。它的目標是找到一個線性關系&#xff08;一條直線或一個超平面&#xff09;&#xff0c;能夠最好地描述一個或多個自變量&#xff08;特征&#xff09;與一個因變量&#xff08;目標&#xff09;之間的關系。利用回歸…

2-5 Dify案例實踐—利用RAG技術構建企業私有知識庫

目錄 一、RAG技術的定義與作用 二、RAG技術的關鍵組件 三、RAG技術解決的問題 四、RAG技術的核心價值與應用場景 五、如何實現利用RAG技術構建企業私有知識庫 六、Dify知識庫實現詳解 七、創建知識庫 1、創建知識庫 2、上傳文檔 3、文本分段與清洗 4、索引方式 5、…