如果你想在你的springboot项目启动完成后,执行一些初始化操作,可以通过实现ApplicationRunner和CommandLineRunner的方式来进行操作。
例如:
这是一个简单的Demo项目
1、实现ApplicationRunner
//注意:类必须交由spring管理,且可以成功创建成一个bean
//注意:类必须交由spring管理,且可以成功创建成一个bean
@Component
public class ApplicationRunnerConfig implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunnerConfig" + args.getSourceArgs());
}
}
2、实现CommandLineRunner
@Component
public class CommandLineRunnerConfig implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunnerConfig" + args);
}
}
直接启动springboot项目可以打印出
2021-12-25 18:01:56.426 INFO 10004 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 3.65 seconds (JVM running for 5.242)
ApplicationRunnerConfig[Ljava.lang.String;@1efdcd5
CommandLineRunnerConfig[Ljava.lang.String;@1efdcd5
也可以设置一些启动参数
打印结果
2021-12-25 18:20:58.124 INFO 7432 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 4.644 seconds (JVM running for 7.156)
ApplicationRunnerConfig[xxxx,bbb]
CommandLineRunnerConfig[xxxx,bbb]
同时可以在类上面使用@Order注解指定多个类的执行顺序,value越小越先执行。
3、实现原理
在SpringApplication.run方法里执行到最后会有
listeners.started(context, timeTakenToStartup);
this.callRunners(context, applicationArguments);// 回调逻辑
} catch (Throwable var12) {
进入callRunners
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());
// 根据@order排序
AnnotationAwareOrderComparator.sort(runners);
Iterator var4 = (new LinkedHashSet(runners)).iterator();
// 具体的执行逻辑
while(var4.hasNext()) {
Object runner = var4.next();
if (runner instanceof ApplicationRunner) {
this.callRunner((ApplicationRunner)runner, args);
}
if (runner instanceof CommandLineRunner) {
this.callRunner((CommandLineRunner)runner, args);
}
}
//ApplicationRunner逻辑
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
runner.run(args);
} catch (Exception var4) {
throw new IllegalStateException("Failed to execute ApplicationRunner", var4);
}
}
//CommandLineRunner逻辑
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
runner.run(args.getSourceArgs());
} catch (Exception var4) {
throw new IllegalStateException("Failed to execute CommandLineRunner", var4);
}
}
4、结论
1、CommandLineRunner实际上是将ApplicationArguments args的结果直接取成String变长字符串,ApplicationRunner可以利用ApplicationArguments args解析一些–xx=xx的参数。
2、不管是CommandLineRunner还是ApplicationRunner,其调用逻辑在springboot启动流程当中,所以异常必须要处理,否则会导致springboot启动失败。