SpringApplication 這個類應(yīng)該算是 Spring Boot 框架 本身的“創(chuàng)新”產(chǎn)物了,因?yàn)樵嫉腟pring框架中并沒有這個類,SpringApplication 里面封裝了一套Spring應(yīng)用的啟動流程,然而這對用戶完全透明,因此我們上手 Spring Boot 時感覺簡潔且輕量。
一般來說默認(rèn)的 SpringApplication 執(zhí)行流程已經(jīng)可以滿足大部分需求,但是 若用戶想干預(yù)這個過程,則可以通過 SpringApplication 在流程某些地方開啟的 擴(kuò)展點(diǎn) 來完成對流程的擴(kuò)展,典型的擴(kuò)展方案那就是使用 set 方法。
我們來舉一個栗子,把我們天天司空見慣的 Spring Boot 應(yīng)用的啟動類來拆解一下寫出來:
@SpringBootApplication
public class CodeSheepApplication {
public static void main( String[] args ) {
// SpringApplication.run( CodeSheepApplication.class args ); // 這是傳統(tǒng)Spring Boot應(yīng)用的啟動,一行代碼搞定,內(nèi)部默認(rèn)做了很多事
SpringApplication app = new SpringApplication( CodeSheepApplication.class );
app.setXXX( ... ); // 用戶自定的擴(kuò)展在此 ?。。? app.run( args );
}
}
這樣一拆解后我們發(fā)現(xiàn),我們也需要先構(gòu)造 SpringApplication 類對象,然后調(diào)用該對象的 run() 方法。
那么接下來就聊聊 SpringApplication 的構(gòu)造過程 以及其 run()方法的流程,搞清楚了這個,那么也就搞清楚了Spring Boot應(yīng)用是如何運(yùn)行起來的了。
SpringApplication實(shí)例的初始化
還是先對照代碼來看:
四個關(guān)鍵的步驟已標(biāo)注在圖中,分別解釋如下:
① 推斷應(yīng)用的類型:創(chuàng)建的是REACTIVE應(yīng)用、SERVLET應(yīng)用、NONE 三種中的某一種
② 使用
SpringFactoriesLoader查找并加載classpath下META-INF/spring.factories文件中所有可用的ApplicationContextInitializer
③ 使用
SpringFactoriesLoader查找并加載classpath下META-INF/spring.factories文件中的所有可用的ApplicationListener
④ 推斷并設(shè)置
main方法的定義類
SpringApplication的run()方法探秘
先看看代碼長啥樣子:
關(guān)鍵步驟都已經(jīng)用數(shù)字標(biāo)注在上圖之中了,除此之外,這里也畫了一個流程圖對照理解:
我們將各步驟總結(jié)精煉如下:
通過
SpringFactoriesLoader加載META-INF/spring.factories文件,獲取并創(chuàng)建SpringApplicationRunListener對象然后由
SpringApplicationRunListener來發(fā)出starting消息創(chuàng)建參數(shù),并配置當(dāng)前
SpringBoot應(yīng)用將要使用的Environment完成之后,依然由
SpringApplicationRunListener來發(fā)出environmentPrepared消息創(chuàng)建
ApplicationContext初始化
ApplicationContext,并設(shè)置Environment,加載相關(guān)配置等由
SpringApplicationRunListener來發(fā)出contextPrepared消息,告知Spring Boot 應(yīng)用使用的ApplicationContext已準(zhǔn)備OK將各種
beans裝載入ApplicationContext,繼續(xù)由SpringApplicationRunListener來發(fā)出contextLoaded消息,告知 Spring Boot 應(yīng)用使用的ApplicationContext已裝填OKrefresh ApplicationContext,完成IoC容器可用的最后一步由
SpringApplicationRunListener來發(fā)出started消息調(diào)用
callRunners(...)方法,讓實(shí)現(xiàn)了ApplicationRunner和CommandLineRunner接口類的run方法得以執(zhí)行,用于在 Spring 應(yīng)用上下文準(zhǔn)備完畢后,執(zhí)行一些額外操作。從而完成最終的程序的啟動。由
SpringApplicationRunListener來發(fā)出running消息,告知程序已運(yùn)行起來了
轉(zhuǎn)載:
https://mp.weixin.qq.com/s/T9o2MAwKX9KHS6TkRdYEog