不知道你有没有接到这种需求,项目启动后立马执行一些逻辑。好比简单的缓存预热,或者上线后的广播之类等等。若是你使用 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 获取更多资讯