SpringBoot之ApplicationRunner解析(spring容器啟動完成執(zhí)行的類)
SpringBoot ApplicationRunner解析
在項目中,可能會遇到這樣一個問題:在項目啟動完成之后,緊接著執(zhí)行一段代碼。
在SpringBoot中,提供了一個接口:ApplicationRunner。
該接口中,只有一個run方法,他執(zhí)行的時機是:spring容器啟動完成之后,就會緊接著執(zhí)行這個接口實現(xiàn)類的run方法。
@Component public class PublishEndpoint implements ApplicationRunner{ ?? ?@Override ?? ?public void run(ApplicationArguments applicationArguments) throws Exception { ?? ??? ?//do something ?? ?} }
這里有幾點說明:
- 這個實現(xiàn)類,要注入到spring容器中,這里使用了@Component注解;
- 在同一個項目中,可以定義多個ApplicationRunner的實現(xiàn)類,他們的執(zhí)行順序通過注解@Order注解或者再實現(xiàn)Ordered接口來實現(xiàn)。
- run方法的參數(shù):ApplicationArguments可以獲取到當前項目執(zhí)行的命令參數(shù)。(比如把這個項目打成jar執(zhí)行的時候,帶的參數(shù)可以通過ApplicationArguments獲取到);
- 由于該方法是在容器啟動完成之后,才執(zhí)行的,所以,這里可以從spring容器中拿到其他已經(jīng)注入的bean。
@SpringBootApplication啟動流程詳解
帶你深入探索SpringApplication執(zhí)行流程
SpringApplication的run方法的實現(xiàn)是我們本次探索之旅的主要線路,該方法的主要流程歸納如下:
1:如果我們使用的是SpringApplication的靜態(tài)run方法,那么,這個方法里面首先要創(chuàng)建一個SpringApplication對象實例,然后調(diào)用這個創(chuàng)建好的SpringApplication的實例方法。在SpringApplication實例初始化的時候,它會提前做幾件事情:
- 根據(jù)classpath里面是否存在某個特征類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應該創(chuàng)建一個為Web應用使用的ApplicationContext類型。
- 使用SpringFactoriesLoader在應用的classpath中查找并加載所有可用的ApplicationContextInitializer。
- 使用SpringFactoriesLoader在應用的classpath中查找并加載所有可用的ApplicationListener。
- 推斷并設(shè)置main方法的定義類。
2: SpringApplication實例初始化完成并且完成設(shè)置后,就開始執(zhí)行run方法的邏輯了,方法執(zhí)行伊始,首先遍歷執(zhí)行所有通過SpringFactoriesLoader可以查找到并加載的SpringApplicationRunListener。調(diào)用它們的started()方法,告訴這些SpringApplicationRunListener,“嘿,SpringBoot應用要開始執(zhí)行咯!”。
3: 創(chuàng)建并配置當前Spring Boot應用將要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4:遍歷調(diào)用所有SpringApplicationRunListener的environmentPrepared()的方法,告訴他們:“當前SpringBoot應用使用的Environment準備好了咯!”。
5:如果SpringApplication的showBanner屬性被設(shè)置為true,則打印banner。 【banner:英文廣告橫幅,在這里面指的是運行時輸出的SpringBoot,還可以進行修改】
6: 根據(jù)用戶是否明確設(shè)置了applicationContextClass類型以及初始化階段的推斷結(jié)果,決定該為當前SpringBoot應用創(chuàng)建什么類型的ApplicationContext并創(chuàng)建完成,然后根據(jù)條件決定是否添加ShutdownHook,決定是否使用自定義的BeanNameGenerator,決定是否使用自定義的ResourceLoader,當然,最重要的,將之前準備好的Environment設(shè)置給創(chuàng)建好的ApplicationContext使用。 【ShutdownHook :停止服務(wù)】
7: ApplicationContext創(chuàng)建好之后,SpringApplication會再次借助Spring-FactoriesLoader,查找并加載classpath中所有可用的ApplicationContext-Initializer,然后遍歷調(diào)用這些ApplicationContextInitializer的initialize(applicationContext)方法來對已經(jīng)創(chuàng)建好的ApplicationContext進行進一步的處理。
8:遍歷調(diào)用所有SpringApplicationRunListener的contextPrepared()方法。
9:最核心的一步,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置加載到已經(jīng)準備完畢的ApplicationContext。
10:遍歷調(diào)用所有SpringApplicationRunListener的contextLoaded()方法。
11:調(diào)用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12:查找當前ApplicationContext中是否注冊有CommandLineRunner,如果有,則遍歷執(zhí)行它們。
13: 正常情況下,遍歷執(zhí)行SpringApplicationRunListener的finished()方法、(如果整個過程出現(xiàn)異常,則依然調(diào)用所有SpringApplicationRunListener的finished()方法,只不過這種情況下會將異常信息一并傳入處理)
去除事件通知點后,整個流程如下:
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring?boot?security權(quán)限管理集成cas單點登錄功能的實現(xiàn)
這篇文章主要介紹了Spring?boot?security權(quán)限管理集成cas單點登錄,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03