ApplicationRunner、InitializingBean、@PostConstruct執(zhí)行順序解讀
概述
開發(fā)中可能會有這樣的場景,需要在容器啟動的時候執(zhí)行一些內(nèi)容。比如讀取配置文件,數(shù)據(jù)庫連接之類的。
SpringBoot給我們提供了兩個接口來幫助我們實現(xiàn)這種需求。
兩個啟動加載接口分別是:CommandLineRunner和ApplicationRunner。
Spring 提供了接口 InitializingBean,jdk提供了@PostConstruct
CommandLineRunner和ApplicationRunner區(qū)別
CommandLineRunner和ApplicationRunner的作用是相同的。不同之處在于CommandLineRunner接口的run()方法接收String數(shù)組作為參數(shù),即是最原始的參數(shù),沒有做任何處理;而ApplicationRunner接口的run()方法接收ApplicationArguments對象作為參數(shù),是對原始參數(shù)做了進一步的封裝。
當(dāng)程序啟動時,我們傳給main()方法的參數(shù)可以被實現(xiàn)CommandLineRunner和ApplicationRunner接口的類的run()方法訪問,即可接收啟動服務(wù)時傳過來的參數(shù)。我們可以創(chuàng)建多個實現(xiàn)CommandLineRunner和ApplicationRunner接口的類。為了使他們按一定順序執(zhí)行,可以使用@Order注解或?qū)崿F(xiàn)Ordered接口。
ApplicationRunner接口的示例
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
@Order(value = 1)
public class JDDRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("這個是測試ApplicationRunner接口");
String strArgs = Arrays.stream(arg0.getSourceArgs()).collect(Collectors.joining("|"));
System.out.println("Application started with arguments:" + strArgs);
}
}啟動時候指定參數(shù):java -jar xxxx.jar data1 data2 data3
這個是測試ApplicationRunner接口
Application started with arguments:data1|data2|data3
CommandLineRunner接口示例
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class TestCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("這個是測試CommandLineRunn接口");
String strArgs = Arrays.stream(args).collect(Collectors.joining("|"));
System.out.println("Application started with arguments:" + strArgs);
}
}啟動時候指定參數(shù):java -jar xxxx.jar data1 data2 data3
運行結(jié)果:
這個是測試CommandLineRunn接口
Application started with arguments:data1|data2|data3
CommandLineRunner和ApplicationRunner的執(zhí)行順序
在spring boot程序中,我們可以使用不止一個實現(xiàn)CommandLineRunner和ApplicationRunner的bean。
為了有序執(zhí)行這些bean的run()方法,可以使用@Order注解或Ordered接口。
@Component
@Order(2)
public class ApplicationRunnerBean1 implements ApplicationRunner {
@Override
public void run(ApplicationArguments arg0) throws Exception {
System.out.println("ApplicationRunnerBean 1");
}
}
@Component
@Order(4)
public class ApplicationRunnerBean2 implements ApplicationRunner {
@Override
public void run(ApplicationArguments arg0) throws Exception {
System.out.println("ApplicationRunnerBean 2");
}
}
@Component
@Order(1)
public class CommandLineRunnerBean1 implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("CommandLineRunnerBean 1");
}
}
@Component
@Order(3)
public class CommandLineRunnerBean2 implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("CommandLineRunnerBean 2");
}
}執(zhí)行結(jié)果:
CommandLineRunnerBean 1 ApplicationRunnerBean 1 CommandLineRunnerBean 2 ApplicationRunnerBean 2
實現(xiàn)多個ApplicationRunner時部分接口未執(zhí)行
@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);
}
}
}只會執(zhí)行RunnerTest1中方法。
通過分析springboot啟動的源碼可以發(fā)現(xiàn),在applicationContext容器加載完成之后,會調(diào)用SpringApplication類的callRunners方法:

該方法中會獲取所有實現(xiàn)了ApplicationRunner和CommandLineRunner的接口bean,然后依次執(zhí)行對應(yīng)的run方法,并且是在同一個線程中執(zhí)行。因此如果有某個實現(xiàn)了ApplicationRunner接口的bean的run方法一直循環(huán)不返回的話,后續(xù)的代碼將不會被執(zhí)行。
InitializingBean接口的用法
InitializingBean接口為bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是繼承該接口的類,在初始化bean的時候都會執(zhí)行該方法。
注意,實現(xiàn)該接口的最好加上Spring的注解注入,比如@Component
@PostConstruct注解的用法
如果想在生成對象時候完成某些初始化操作,而偏偏這些初始化操作又依賴于依賴注入,那么就無法在構(gòu)造函數(shù)中實現(xiàn)。為此,可以使用@PostConstruct注解一個方法來完成初始化,@PostConstruct注解的方法將會在依賴注入完成后被自動調(diào)用。
優(yōu)先級: Constructor >> @Autowired >> @PostConstruct
@Component
public class Test implements InitializingBean, ApplicationRunner, CommandLineRunner {
@PostConstruct
public void init(){
System.out.println("PostConstruct 方法執(zhí)行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean 方法執(zhí)行");
}
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("這個是測試ApplicationRunner接口");
}
@Override
public void run(String... args) throws Exception {
System.out.println("這個是測試CommandLineRunn接口");
}
}PostConstruct 方法執(zhí)行 InitializingBean 方法執(zhí)行
這個是測試ApplicationRunner接口 這個是測試CommandLineRunn接口
由此可知: @PostConstruct>InitializingBean>ApplicationRunner>CommandLineRunner
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- springboot中ApplicationRunner執(zhí)行順序問題小結(jié)
- SpringBoot使用CommandLineRunner和ApplicationRunner執(zhí)行初始化業(yè)務(wù)方式
- Spring中的ApplicationRunner接口的使用詳解
- Spring接口ApplicationRunner用法詳解
- SpringBoot之ApplicationRunner解析(spring容器啟動完成執(zhí)行的類)
- SchedulingConfigurer實現(xiàn)動態(tài)定時,導(dǎo)致ApplicationRunner無效解決
- SpringBoot實現(xiàn)多個ApplicationRunner時部分接口未執(zhí)行問題
相關(guān)文章
使用springboot防止反編譯proguard+xjar
介紹了三種代碼混淆和加密工具的使用方法:ProGuard、Xjar和ClassFinal,ProGuard用于混淆Java字節(jié)碼,Xjar提供對JAR包內(nèi)資源的加密和動態(tài)解密,而ClassFinal則支持直接加密JAR包或WAR包,通過預(yù)研和實際操作2024-11-11
java遠(yuǎn)程連接Linux執(zhí)行命令的3種方式完整代碼
在一些Java應(yīng)用程序中需要執(zhí)行一些Linux系統(tǒng)命令,例如服務(wù)器資源查看、文件操作等,這篇文章主要給大家介紹了關(guān)于java遠(yuǎn)程連接Linux執(zhí)行命令的3種方式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06
dubbo?filter中有關(guān)bean注入和配置文件讀取方式
這篇文章主要介紹了dubbo?filter中有關(guān)bean注入和配置文件讀取方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
SpringBoot3+SpringSecurity6前后端分離的項目實踐
SpringSecurity6 的用法和以前版本的有較大差別,本文主要介紹了SpringBoot3+SpringSecurity6前后端分離的項目實踐,具有一定的參考價值,感興趣的可以了解一下2023-12-12
SpringBoot中的@ConfigurationProperties注解解析
這篇文章主要介紹了SpringBoot中的@ConfigurationProperties注解解析,Spring源碼中大量使用了ConfigurationProperties注解,通過與其他注解配合使用,能夠?qū)崿F(xiàn)Bean的按需配置,該注解可以放在類上,也可以放在方法上,需要的朋友可以參考下2023-11-11

