SpringBoot實(shí)現(xiàn)多個(gè)ApplicationRunner時(shí)部分接口未執(zhí)行問題
SpringBoot多個(gè)ApplicationRunner時(shí)部分接口未執(zhí)行
在springboot的項(xiàng)目中,需要在容器啟動(dòng)之后執(zhí)行一些操作。springboot提供了ApplicationRunner和CommandLineRunner兩個(gè)接口可以幫助我們實(shí)現(xiàn)這種需求。
當(dāng)項(xiàng)目中實(shí)現(xiàn)了多個(gè)ApplicationRunner接口,并且其中一個(gè)使用了類似于while(true)這樣不會(huì)退出的循環(huán)體。將會(huì)導(dǎo)致后續(xù)的ApplicationRunner接口不會(huì)被調(diào)用。
如下:
@Component
@Slf4j
public class RunnerTest1 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
while (true) {
System.out.println("this is RunnerTest1");
Thread.sleep(100);
}
}
}@Component
@Slf4j
public class RunnerTest2 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
while (true) {
System.out.println("this is RunnerTest2");
Thread.sleep(100);
}
}
}輸出結(jié)果:

可以看到項(xiàng)目啟動(dòng)后RunnerTest2 將不會(huì)被執(zhí)行。
通過分析springboot啟動(dòng)的源碼可以發(fā)現(xiàn),在applicationContext容器加載完成之后,會(huì)調(diào)用SpringApplication類的callRunners方法

該方法中會(huì)獲取所有實(shí)現(xiàn)了ApplicationRunner和CommandLineRunner的接口bean,然后依次執(zhí)行對(duì)應(yīng)的run方法,并且是在同一個(gè)線程中執(zhí)行。
因此如果有某個(gè)實(shí)現(xiàn)了ApplicationRunner接口的bean的run方法一直循環(huán)不返回的話,后續(xù)的代碼將不會(huì)被執(zhí)行。
ApplicationRunner實(shí)現(xiàn)項(xiàng)目啟動(dòng)就執(zhí)行的功能
ApplicationRunner
是一個(gè)接口,常用于項(xiàng)目啟動(dòng)后,(也就是ApringApplication.run()執(zhí)行結(jié)束),立馬執(zhí)行某些邏輯。
可用于項(xiàng)目的準(zhǔn)備工作,比如加載配置文件,加載執(zhí)行流,定時(shí)任務(wù)等等。
如何使用ApplicationRunner
這里有幾點(diǎn)說明:
- 1:這個(gè)實(shí)現(xiàn)類,要注入到spring容器中,這里使用了@Component注解;
- 2:在同一個(gè)項(xiàng)目中,可以定義多個(gè)ApplicationRunner的實(shí)現(xiàn)類,他們的執(zhí)行順序通過注解@Order注解或者再實(shí)現(xiàn)Ordered接口來實(shí)現(xiàn)。
- 3:run方法的參數(shù):ApplicationArguments可以獲取到當(dāng)前項(xiàng)目執(zhí)行的命令參數(shù)。(比如把這個(gè)項(xiàng)目打成jar執(zhí)行的時(shí)候,帶的參數(shù)可以通過ApplicationArguments獲取到);
- 4:由于該方法是在容器啟動(dòng)完成之后,才執(zhí)行的,所以,這里可以從spring容器中拿到其他已經(jīng)注入的bean。
(可以有多個(gè)實(shí)例實(shí)現(xiàn)該接口,但是一般需要增加注解@Order來指定加載順序)
@Component
@Order(2)
public class JDDRunner implements ApplicationRunner {
? ? @Override
? ? public void run(ApplicationArguments args) throws Exception {
? ? ? ? System.out.println(args);
? ? ? ? System.out.println("這個(gè)是測(cè)試ApplicationRunner接口");
? ? }
}實(shí)現(xiàn)ApplicationRunner接口,重寫run方法,定義具體的執(zhí)行邏輯
@Order注解,用于決定多個(gè)bean的執(zhí)行順序,按照值從小到大執(zhí)行 (值可為負(fù)數(shù))
- @Order(-1)優(yōu)先于@Order(0)
- @Order(1)優(yōu)先于@Order(2)
還有個(gè)接口
也可以實(shí)現(xiàn)和ApplicationRunner一樣的功能
- CommandLineRunner
- CommandLineRunner接口的run方法接收的參數(shù)為String數(shù)組
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java基于分治算法實(shí)現(xiàn)的線性時(shí)間選擇操作示例
這篇文章主要介紹了Java基于分治算法實(shí)現(xiàn)的線性時(shí)間選擇操作,涉及java排序、比較、計(jì)算等相關(guān)操作技巧,需要的朋友可以參考下2017-11-11
關(guān)于SpringBoot整合Canal數(shù)據(jù)同步的問題
大家都知道canal是阿里巴巴旗下的一款開源工具,純java開發(fā),支持mysql數(shù)據(jù)庫,本文給大家介紹SpringBoot整合Canal數(shù)據(jù)同步的問題,需要的朋友可以參考下2022-03-03
Spring Boot異步調(diào)用@Async過程詳解
這篇文章主要介紹了Spring Boot異步調(diào)用@Async過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
SpringMVC實(shí)現(xiàn)表單驗(yàn)證功能詳解
這篇文章主要為大家詳細(xì)介紹了SpringMVC 表單驗(yàn)證的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10

