SpringBoot 應用程序啓動過程探祕

本文共 946字,閱讀大約須要 3分鐘 !spring


概述

說到接觸 SpringBoot 伊始,給我第一映像最深的是有兩個關鍵元素:bash

SpringBoot 的兩個關鍵元素

對照上面的典型代碼,這個兩個元素分別是:markdown

  • @SpringBootApplication
  • SpringApplication 以及 run() 方法

關於 @SpringBootApplication 註解的剖析已經在上文:《SpringBoot 中 @SpringBootApplication註解背後的三體結構探祕》 中完成了,其實它背後就是一個三體結構,只是 SpringBoot給了其一個包裝而已。那麼本文咱們就來看看這個 SpringApplication 以及 run() 方法 究竟是個什麼鬼,它背後又隱藏了哪些奧祕呢?app

注: 本文首發於 My Personal Blog,歡迎光臨 小站框架

本文內容腦圖以下:oop

本文內容腦圖


SpringApplication 驚鴻一瞥

SpringApplication 這個類應該算是 SpringBoot 框架 的「創新」產物了,原始的 Spring中並無這個類,SpringApplication 裏面封裝了一套 Spring 應用的啓動流程,然而這對用戶徹底透明,所以咱們上手 SpringBoot 時感受簡潔、輕量。學習

通常來講默認的 SpringApplication 執行流程已經能夠知足大部分需求,可是 若用戶想幹預這個過程,則能夠經過 SpringApplication 在流程某些地方開啓的 擴展點 來完成對流程的擴展,典型的擴展方案那就是使用 set 方法。spa

咱們來舉一個栗子,把咱們每天司空見慣的 SpringBoot 應用的啓動類來拆解一下寫出來:code

@SpringBootApplication
public class CodeSheepApplication {
	public static void main( String[] args ) {
		// SpringApplication.run( CodeSheepApplication.class args ); // 這是傳統SpringBoot應用的啓動,一行代碼搞定,內部默認作了不少事
		SpringApplication app = new SpringApplication( CodeSheepApplication.class );
		app.setXXX( ... ); // 用戶自定的擴展在此 !!!
		app.run( args );
	}
}
複製代碼

這樣一拆解後咱們發現,咱們也須要先構造 SpringApplication 類對象,而後調用該對象的 run() 方法。那麼接下來就講講 SpringApplication 的構造過程 以及其 run() 方法的流程,搞清楚了這個,那麼也就搞清楚了SpringBoot應用是如何運行起來的!orm


SpringApplication 實例的初始化

咱們對照代碼來看:

SpringApplication 實例的初始化代碼

四個關鍵的步驟已標註在圖中,分別解釋以下:

  • 推斷應用的類型:建立的是 REACTIVE應用、SERVLET應用、NONE 三種中的某一種

推斷應用的類型

  • 使用 SpringFactoriesLoader查找並加載 classpath下 META-INF/spring.factories文件中全部可用的 ApplicationContextInitializer

ApplicationContextInitializer 加載

  • 使用 SpringFactoriesLoader查找並加載 classpath下 META-INF/spring.factories文件中的全部可用的 ApplicationListener

ApplicationListener 加載

  • 推斷並設置 main方法的定義類

推斷並設置main方法的定義類



SpringApplication 的run()方法探祕

先看看代碼長啥樣子:

SpringApplication 的run()方法背後的奧祕

各個主要步驟我已經標註在上圖之中了,除此以外,我也按照本身的理解畫了一個流程圖以下所示,能夠對照數字標示看一下:

SpringBoot 應用啓動流程圖

咱們將各步驟總結精煉以下:

  1. 經過 SpringFactoriesLoader 加載 META-INF/spring.factories 文件,獲取並建立 SpringApplicationRunListener 對象

  2. 而後由 SpringApplicationRunListener 來發出 starting 消息

  3. 建立參數,並配置當前 SpringBoot 應用將要使用的 Environment

  4. 完成以後,依然由 SpringApplicationRunListener 來發出 environmentPrepared 消息

  5. 建立 ApplicationContext

  6. 初始化 ApplicationContext,並設置 Environment,加載相關配置等

  7. SpringApplicationRunListener 來發出 contextPrepared 消息,告知SpringBoot 應用使用的 ApplicationContext 已準備OK

  8. 將各類 beans 裝載入 ApplicationContext,繼續由 SpringApplicationRunListener 來發出 contextLoaded 消息,告知 SpringBoot 應用使用的 ApplicationContext 已裝填OK

  9. refresh ApplicationContext,完成IoC容器可用的最後一步

  10. SpringApplicationRunListener 來發出 started 消息

  11. 完成最終的程序的啓動

  12. SpringApplicationRunListener 來發出 running 消息,告知程序已運行起來了

至此,全流程結束!



後記

因爲能力有限,如有錯誤或者不當之處,還請你們批評指正,一塊兒學習交流!



長按掃描 下面的 當心心 來訂閱做者公衆號 CodeSheep,獲取更多 務實、能看懂、可復現的 原創文 ↓↓↓

CodeSheep · 程序羊
相關文章
相關標籤/搜索