正如题目标题所讲,一个项目启动时,我需要执行指定任务,如:初始化数据库数据,外部配置参数加载到缓存,等等。说到这不得不讲讲ApplicationRunner和CommandLineRunner,这两个又有什么区别呢?让我们看看源吧!
ApplicationRunner
/**
* Interface used to indicate that a bean should <em>run</em> when it is contained within
* a {@link SpringApplication}. Multiple {@link ApplicationRunner} beans can be defined
* within the same application context and can be ordered using the {@link Ordered}
* interface or {@link Order @Order} annotation.
*
* @author Phillip Webb
* @since 1.3.0
* @see CommandLineRunner
*/
@FunctionalInterface
public interface ApplicationRunner {
/**
* Callback used to run the bean.
* @param args incoming application arguments
* @throws Exception on error
*/
void run(ApplicationArguments args) throws Exception;
}
CommandLineRunner
/**
* Interface used to indicate that a bean should <em>run</em> when it is contained within
* a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined
* within the same application context and can be ordered using the {@link Ordered}
* interface or {@link Order @Order} annotation.
* <p>
* If you need access to {@link ApplicationArguments} instead of the raw String array
* consider using {@link ApplicationRunner}.
*
* @author Dave Syer
* @see ApplicationRunner
*/
@FunctionalInterface
public interface CommandLineRunner {
/**
* Callback used to run the bean.
* @param args incoming main method arguments
* @throws Exception on error
*/
void run(String... args) throws Exception;
}
乍眼一看就名字不一样,再一看还有传入的参数不一样其他都一样,再看看他们在SpringApplication中的区别
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
这不是就是复制黏贴吗?源码就这?让我来我也行,哈哈
其实看到上面的注释也大概明白,可以实现多个,执行顺序可以实现Ordered接口或根据@Order注解来排序。
CommandLineRunner的使用示例
@Component
@Order(1)
public class MyCommandLineRunner1 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner1------>" + Arrays.toString(args));
}
}
@Component
@Order(2)
public class MyCommandLineRunner2 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner2------>" + Arrays.toString(args));
}
}
当然你也可以这样写
@Component
//@Order(1)
public class MyCommandLineRunner1 implements CommandLineRunner, Ordered {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner1------>" + Arrays.toString(args));
}
@Override
public int getOrder() {
return 1;
}
}
@Component
//@Order(2)
public class MyCommandLineRunner2 implements CommandLineRunner, Ordered {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner2------>" + Arrays.toString(args));
}
@Override
public int getOrder() {
return 2;
}
}
我们可以配置在系统启动时需要传入的参数,这里以 intelliJ IDEA 为例,单击右上角的编辑启动配置。
参数之间使用空格隔开。
项目启动后的运行结果
ApplicationRunner的使用示例
@Component
@Order(1)
public class MyApplicationRunner1 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("MyApplicationRunner1------>" + Arrays.toString(args.getSourceArgs()));
}
}
@Component
@Order(2)
public class MyApplicationRunner2 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("MyApplicationRunner2------>" + Arrays.toString(args.getSourceArgs()));
}
}
项目启动后的运行结果
你会发现很多人都会用ApplicationRunner,你自己去写,然后品,你细品,你就知道原因了。