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