Spring Boot深入原理 - SpringApplication啟動原理
Spring Boot深入原理 - SpringApplication啟動原理
我們知道,如果不需要特殊的配置,只需要在main方法裏調用SpringApplicatio.run()方法即可啟動Spring Boot應用:
- public static void main(String[] args) throws Exception {
- SpringApplication.run(Application.class, args);
- }
作為深入原理的第一篇,我們先來看下Spring Boot應用是怎麽啟動的。
SpringApplication啟動流程
SpringApplication的啟動過程非常復雜,下面是在調用SpringApplication.run方法之後啟動的關鍵動作:
既然要了解SpringApplication的啟動流程,第一步當然是進入源碼裏看看嘍:
- public ConfigurableApplicationContext run(String... args) {
- StopWatch stopWatch = new StopWatch();
- stopWatch.start();
- ConfigurableApplicationContext context = null;
- FailureAnalyzers analyzers = null;
- configureHeadlessProperty();
- //初始化監聽器
- SpringApplicationRunListeners listeners = getRunListeners(args);
- //發布ApplicationStartedEvent
- listeners.starting();
- try {
- //裝配參數和環境
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(
- args);
- ConfigurableEnvironment environment = prepareEnvironment(listeners,
- applicationArguments);
- //打印Banner
- Banner printedBanner = printBanner(environment);
- //創建ApplicationContext()
- context = createApplicationContext();
- analyzers = new FailureAnalyzers(context);
- //裝配Context
- prepareContext(context, environment, listeners, applicationArguments,
- printedBanner);
- //refreshContext
- refreshContext(context);
- //afterRefresh
- afterRefresh(context, applicationArguments);
- //發布ApplicationReadyEvent
- listeners.finished(context, null);
- stopWatch.stop();
- if (this.logStartupInfo) {
- new StartupInfoLogger(this.mainApplicationClass)
- .logStarted(getApplicationLog(), stopWatch);
- }
- return context;
- }
- catch (Throwable ex) {
- handleRunFailure(context, listeners, analyzers, ex);
- throw new IllegalStateException(ex);
- }
- }
第一步,初始化監聽器
這裏會初始化Spring Boot自帶的監聽器,以及添加到SpringApplication的自定義監聽器。
初始化監聽器的調用關系很深,為了節省篇幅,就不貼源碼了,稍後用專門的文章細聊。
第二步,發布ApplicationStartedEvent事件
到這一步,Spring Boot會發布一個ApplicationStartedEvent事件。如果你想在這個時候執行一些代碼可以通過實現ApplicationListener接口實現;
下面是ApplicationListener接口的定義,註意這裏有個<E extends ApplicationEvent>
- public interface ApplicationListener<E extends ApplicationEvent> extends EventListener
例如,你想監聽ApplicationStartedEvent事件,你可以這樣定義:
- public class ApplicationStartedListener implements ApplicationListener<ApplicationStartedEvent>
然後通過SpringApplication.addListener(..)添加進去即可。
第三步,裝配參數和環境
在這一步,首先會初始化參數,然後裝配環境,確定是web環境還是非web環境。
第四步,發布ApplicationEnvironmentPreparedEvent事件
準確的說,這個應該屬於第三步,在裝配完環境後,就觸發ApplicationEnvironmentPreparedEvent事件。如果想在這個時候執行一些代碼,可以訂閱這個事件的監聽器,方法同第二步。
第五步,打印Banner
看過Spring Boot實例教程 - 自定義Banner的同學會很熟悉,啟動的Banner就是在這一步打印出來的。
第六步,創建ApplicationContext
這裏會根據是否是web環境,來決定創建什麽類型的ApplicationContext,ApplicationContext不要多說了吧,不知道ApplicationContext是啥的同學,出門左轉補下Spring基礎知識吧。
第七步,裝配Context
這裏會設置Context的環境變量、註冊Initializers、beanNameGenerator等。
第八步,發布ApplicationPreparedEvent事件
這裏放在第七步會更準確,因為這個是在裝配Context的時候發布的。
值得註意的是:這裏是假的,假的,假的,源碼中是空的,並沒有真正發布ApplicationPreparedEvent事件。不知道作者這麽想的???
第九步,註冊、加載等
註冊springApplicationArguments、springBootBanner,加載資源等。
第十步,發布ApplicationPreparedEvent事件
註意,到這裏才是真正發布了ApplicationPreparedEvent事件。這裏和第八步好讓人誤解。
第十一步,refreshContext
裝配context beanfactory等非常重要的核心組件。
第十二步,afterRefreshContext
這裏會調用自定義的Runners,不知道Runners是什麽的同學,請參考Spring Boot官方文檔 - SpringApplication
第十三步,發布ApplicationReadyEvent事件
最後一步,發布ApplicationReadyEvent事件,啟動完畢,表示服務已經可以開始正常提供服務了。通常我們這裏會監聽這個事件來打印一些監控性質的日誌,表示應用正常啟動了。添加方法同第二步。
註意:如果啟動失敗,這一步會發布ApplicationFailedEvent事件。
到這裏,Spring Boot啟動的一些關鍵動作就介紹完了。
總結
說是深入,本篇文章更像是一個概括性的介紹。因為每個關鍵動作內容都很多,都很值得深入研究,都放在這裏顯然空間太小,接下來將會分章節深入每個關鍵動作。
Spring Boot深入原理 - SpringApplication啟動原理