不知道你有沒有接到這種需求,項目啓動後立馬執行一些邏輯。好比簡單的緩存預熱,或者上線後的廣播之類等等。若是你使用 Spring Boot 框架的話就能夠藉助其提供的接口CommandLineRunner
和 ApplicationRunner
來實現。java
org.springframework.boot.CommandLineRunner
是Spring Boot提供的一個接口,當你實現該接口並將之注入Spring IoC容器後,Spring Boot應用啓動後就會執行其run
方法。一個Spring Boot能夠存在多個CommandLineRunner
的實現,當存在多個時,你能夠實現Ordered
接口控制這些實現的執行順序(Order 數值越大優先級越低)。接下來咱們來聲明兩個實現並指定順序:spring
優先執行:編程
package cn.felord; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; /** * 優先級最高 * 該類指望在springboot 啓動後第一順位執行 * @author felord.cn * @since 12:57 **/ @Slf4j @Component public class HighOrderCommandLineRunner implements CommandLineRunner, Ordered { @Override public void run(String... args) throws Exception { for (String arg : args) { log.info("arg = " + arg); } log.info("i am highOrderRunner"); } @Override public int getOrder() { return Integer.MIN_VALUE+1; } }
第二順序執行:數組
package cn.felord; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; /** * 優先級低於{@code HighOrderCommandLineRunner} * @author felord.cn * @since 12:59 **/ @Slf4j @Component public class LowOrderCommandLineRunner implements CommandLineRunner, Ordered { @Override public void run(String... args) throws Exception { log.info("i am lowOrderRunner"); } @Override public int getOrder() { return Integer.MIN_VALUE+1; } }
而後啓動Spring Boot應用後,控制檯按照預約的順序打印出告終果:緩存
2020-05-30 23:11:03.685 INFO 11976 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2020-05-30 23:11:03.701 INFO 11976 --- [ main] c.f.Application : Started SpringBootApplication in 4.272 seconds (JVM running for 6.316) 2020-05-30 23:11:03.706 INFO 11976 --- [ main] c.f.HighOrderCommandLineRunner : i am highOrderRunner 2020-05-30 23:11:03.706 INFO 11976 --- [ main] c.f.LowOrderCommandLineRunner : i am lowOrderRunner
在Spring Boot 1.3.0又引入了一個和CommandLineRunner
功能同樣的接口ApplicationRunner
。CommandLineRunner
接收可變參數String... args
,而ApplicationRunner
接收一個封裝好的對象參數ApplicationArguments
。除此以外它們功能徹底同樣,甚至連方法名都同樣。 聲明一個ApplicationRunner
並讓它優先級最低:tomcat
package cn.felord; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; import java.util.Set; /** * 優先級最低 * @author felord.cn * @since 13:00 **/ @Slf4j @Component public class DefaultApplicationRunner implements ApplicationRunner, Ordered { @Override public void run(ApplicationArguments args) throws Exception { log.info("i am applicationRunner"); Set<String> optionNames = args.getOptionNames(); log.info("optionNames = " + optionNames); String[] sourceArgs = args.getSourceArgs(); log.info("sourceArgs = " + Arrays.toString(sourceArgs)); List<String> nonOptionArgs = args.getNonOptionArgs(); log.info("nonOptionArgs = " + nonOptionArgs); List<String> optionValues = args.getOptionValues("foo"); log.info("optionValues = " + optionValues); } @Override public int getOrder() { return Integer.MIN_VALUE+2; } }
按照順序打印了三個類的執行結果:springboot
2020-06-01 13:02:39.420 INFO 19032 --- [ main] c.f.MybatisResultmapApplication : Started MybatisResultmapApplication in 1.801 seconds (JVM running for 2.266) 2020-06-01 13:02:39.423 INFO 19032 --- [ main] c.f.HighOrderCommandLineRunner : i am highOrderRunner 2020-06-01 13:02:39.423 INFO 19032 --- [ main] c.f.LowOrderCommandLineRunner : i am lowOrderRunner 2020-06-01 13:02:39.423 INFO 19032 --- [ main] c.f.DefaultApplicationRunner : i am applicationRunner 2020-06-01 13:02:39.423 INFO 19032 --- [ main] c.f.DefaultApplicationRunner : optionNames = [] 2020-06-01 13:02:39.423 INFO 19032 --- [ main] c.f.DefaultApplicationRunner : sourceArgs = [] 2020-06-01 13:02:39.423 INFO 19032 --- [ main] c.f.DefaultApplicationRunner : nonOptionArgs = [] 2020-06-01 13:02:39.423 INFO 19032 --- [ main] c.f.DefaultApplicationRunner : optionValues = null
Ordered
接口並不能被@Order
註解所代替。
相信不少同窗看到這裏都開始對這兩個run
方法的入參感興趣了。Spring Boot應用啓動時是能夠接受參數的,換句話說也就是Spring Boot
的main
方法是能夠接受參數的。這些參數經過命令行 java -jar yourapp.jar <param> 來傳遞。CommandLineRunner
會原封不動照單全收這些接口,這些參數也能夠封裝到ApplicationArguments
對象中供ApplicationRunner
調用。 咱們來認識一下ApplicationArguments
的相關方法:bash
Set
字符串集合。如 --spring.profiles.active=dev --debug
將返回["spring.profiles.active","debug"]
。--foo=bar --foo=baz
將返回["bar","baz"]
。接下來咱們試驗一波,你能夠經過下面的命令運行一個 Spring Boot應用 Jarapp
java -jar yourapp.jar --foo=bar --foo=baz --dev.name=碼農小胖哥 java felordcn
或者在IDEA開發工具中打開Spring Boot應用main
方法的配置項,進行以下配置,其餘IDE工具同理。框架
運行Spring Boot應用,將會打印出:
2020-06-01 15:04:31.490 INFO 13208 --- [ main] c.f.HighOrderCommandLineRunner : arg = --foo=bar 2020-06-01 15:04:31.490 INFO 13208 --- [ main] c.f.HighOrderCommandLineRunner : arg = --foo=baz 2020-06-01 15:04:31.490 INFO 13208 --- [ main] c.f.HighOrderCommandLineRunner : arg = --dev.name=碼農小胖哥 2020-06-01 15:04:31.490 INFO 13208 --- [ main] c.f.HighOrderCommandLineRunner : arg = java 2020-06-01 15:04:31.490 INFO 13208 --- [ main] c.f.HighOrderCommandLineRunner : arg = felordcn 2020-06-01 15:04:31.491 INFO 13208 --- [ main] c.f.HighOrderCommandLineRunner : i am highOrderRunner 2020-06-01 15:04:31.491 INFO 13208 --- [ main] c.f.LowOrderCommandLineRunner : i am lowOrderRunner 2020-06-01 15:04:31.491 INFO 13208 --- [ main] c.f.DefaultApplicationRunner : i am applicationRunner 2020-06-01 15:04:31.491 INFO 13208 --- [ main] c.f.DefaultApplicationRunner : optionNames = [dev.name, foo] 2020-06-01 15:04:31.491 INFO 13208 --- [ main] c.f.DefaultApplicationRunner : sourceArgs = [--foo=bar, --foo=baz, --dev.name=碼農小胖哥, java, felordcn] 2020-06-01 15:04:31.491 INFO 13208 --- [ main] c.f.DefaultApplicationRunner : nonOptionArgs = [java, felordcn] 2020-06-01 15:04:31.491 INFO 13208 --- [ main] c.f.DefaultApplicationRunner : optionValues = [bar, baz]
而後你就能夠根據實際須要動態地執行一些邏輯。
今天咱們對CommandLineRunner
和ApplicationRunner
進行了講解,從用法到順序執行,又對Spring Boot傳遞參數進行了介紹和演示,但願對你有所幫助。多多關注:碼農小胖哥,更多編程乾貨分享給你。
關注公衆號:Felordcn 獲取更多資訊