Springboot ApplicationRunner的使用解讀
Springboot ApplicationRunner使用
ApplicationRunner介紹
ApplicationRunner是在應用容器啟動之后會回調(diào)到,在ApplicationStartedListener調(diào)用之后被調(diào)用。
如果說ApplicationListener中有阻塞,那么ApplicationRunner也都不會被調(diào)用。
@Component
public class ApplicationRunnerTest implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(args);
}
}我們可以在applicationRunner中做一些異步啟動的操作,比如實例化Kafka客戶端,異步加載緩存等等在服務啟動之后不立馬提供服務的操作。

通過分析源碼可以知道runner實在容器加載完成以及ApplicationStartedListener調(diào)用之后進行回調(diào)的。
ApplicationRunner為什么不被調(diào)用
問題描述
在項目中寫了一個ApplicationRunner 來啟動消費隊列線程,結果啟動的時候applicationRunner的run方法死活不被調(diào)用。
問題分析
通過debug發(fā)現(xiàn),在springboot初始化完環(huán)境refresh context之后就會調(diào)用started listener然后調(diào)用application runner,如果started listner 存在阻塞的話就會導致后續(xù)的application runner 不被運行。
而我在另一個組件中使用ApplicationListener<ApplicationStartedEvent> 去啟動了netty server,啟動netty server會導致當前線程阻塞以至于application runner 不被調(diào)用。
問題解決
在listener和Runner當中盡量啟用線程來跑阻塞而不是直接去跑阻塞任務。
ApplicationRunner的作用是什么?
有時針對一些特殊的業(yè)務場景,需要在系統(tǒng)啟動時執(zhí)行某些任務,如:配置文件的加載、數(shù)據(jù)庫的初始化等等操作。
SpringBoot 提供了兩種解決方案:
- 一種是使用CommandLineRunner
- 另一種是使用 ApplicationRunner
基本原理
項目在啟動時會遍歷所有的 ApplicationRunner 的實現(xiàn)類并調(diào)用其中的 run 方法,如果在系統(tǒng)中有多個 ApplicationRunner的實現(xiàn)類,可以使用 @Order 注解對這些實現(xiàn)類的調(diào)用順序進行排序(數(shù)字越小越先執(zhí)行);run方法的參數(shù)是系統(tǒng)啟動時傳入的參數(shù),即入口類中main方法的參數(shù)(在調(diào)用SpringApplication.run方法時傳入到 SpringBoot項目的上下文環(huán)境中)。
如何使用
@Component
@Slf4j
@Order(1)
public class MyApplicationRunner implements ApplicationRunner {
?? ?// ApplicationArguments, 需要區(qū)分選項參數(shù)和非選項參數(shù);
?? ?// 選項參數(shù), 通過ApplicationArguments的getOptionNames()方法獲取所有選項名稱即參數(shù)的KEY, 然后通過 getOptionValues()方法根據(jù)參數(shù)KEY, 獲取實際值(它會返回一個列表字符串), 一般為: --user-name=ROCKY --age=30
?? ?// 非選項參數(shù), 通過ApplicationArguments的getNonOptionArgs()方法獲取一個參數(shù)值數(shù)組;
? ? @Override
? ? public void run(ApplicationArguments args) throws Exception {
? ? ?? ?// TO DO SOMETHING...
? ? }
}ApplicationRunner和CommandLineRunner的區(qū)別
@Component
@Slf4j
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
? ? @Override
? ? public void run(String... args) throws Exception {
? ? ?? ?// TO DO SOMETHING...
? ? }
}?ApplicationRunner與CommandLineRunner的主要區(qū)別體現(xiàn)在run方法的參數(shù)上,CommandLineRunner中的run方法的參數(shù)是參數(shù)數(shù)組;ApplicationRunner中的run方法的參數(shù)是ApplicationArguments對象。
執(zhí)行順序
系統(tǒng)支持創(chuàng)建多個CommandLineRunner或ApplicationRunner的實現(xiàn)類,可以使用@Order注解或?qū)崿F(xiàn)Ordered接口,來設定各個實現(xiàn)類的執(zhí)行順序。
選項參數(shù)與非選項參數(shù)
- 選項參數(shù):可以理解為Spring Boot 提供的參數(shù)格式,以–開頭,使用=分割鍵值對,如:java -jar XXX.jar --name=ROCKY --age=30 --spring.profiles.active=dev;
- 非選項參數(shù):不是以–開頭,也沒有設置值的單一參數(shù)KEY只有值,如:java -jar XXX.jar --name=ROCKY --age=30 --spring.profiles.active=dev 陜西 西安 雁塔區(qū),其中"陜西 西安 雁塔區(qū)" 就是非選項參數(shù);
- 系統(tǒng)參數(shù):-Dxxxx是設置JAVA運行上下文的參數(shù)語法,用于配置一些環(huán)境變量,如:java -jar XXX.jar -Dserver.port=8081 --name=ROCKY --age=30 --spring.profiles.active=dev 陜西 西安 雁塔區(qū),其中"-Dserver.port"就是系統(tǒng)參數(shù)。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringBoot統(tǒng)一返回處理出現(xiàn)cannot?be?cast?to?java.lang.String異常解決
這篇文章主要給大家介紹了關于SpringBoot統(tǒng)一返回處理出現(xiàn)cannot?be?cast?to?java.lang.String異常解決的相關資料,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2023-09-09
commons fileupload實現(xiàn)文件上傳的實例代碼
這篇文章主要介紹了commons fileupload實現(xiàn)文件上傳的實例代碼,包括文件上傳的原理分析等相關知識點,本文給大家介紹的非常詳細,具有參考借鑒價值,感興趣的朋友一起看看吧2016-10-10
SpringBoot啟動類@SpringBootApplication注解背后的秘密
這篇文章主要介紹了SpringBoot啟動類@SpringBootApplication注解背后的秘密,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
SpringBoot測試配置屬性與web啟動環(huán)境超詳細圖解
Web開發(fā)的核心內(nèi)容主要包括內(nèi)嵌的Servlet容器和SpringMVCSpringBoot使用起來非常簡潔,大部分配置都有SpringBoot自動裝配,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-10-10

