SpringBoot的启动加载器
目录
1.概念
SpringBoot的启动加载器是SpringBoot 容器启动完成后被启动的类的一种机制。
可以实现项目启动后需要默认调用的功能。
2. 实现
2.1 两种方式
- 实现 CommandLineRunner接口
- 实现 ApplicationRunner接口
2.2 调用顺序的实现
- 使用 order 注解
3. 实现 CommandLineRunner 接口的代码
@Component
public class FirstCommandlineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println(">>>> startup first runner <<<<<");
}
}
①实现 CommandLineRunner 接口,② 重新 run方法,③ 添加Component 注解
4. 实现ApplicationRunner 接口的代码
@Component
@Order(1)
public class FirstApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(">>>>> First Application runner start <<<<<<");
}
}
①实现ApplicationRunner 接口,②重新 run 方法 ③添加Component 注解
如果要实现先后顺序添加 Order(优先级)
5. 启动器的实现原理
开发人员实现 ApplicationRunner 接口或者 CommandLineRunner 接口重写 run 方法,run 方法为启动器执行的方法,可以放入业务相关的内容。
容器在启动中调用 SpringApplication的 run() 方法内容器初始化相关的方法调用完成后 调用 callRunners 方法对启动器进行获取及调用,
callRunners 方法传入 applicationContext 对象和参数,方法内获取实现了上面两个接口的类然后获取对应的方法及参数实现对启动类的调用。
- 容器 run 方法调用完成后调用 call runners 方法
SpringApplication 类中 run() 方法
listeners.started(context);
callRunners(context, applicationArguments);
- 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());
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);
}
}
}
- 实现了 ApplicationRunner接口的调用
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try { // args 为对象
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}
- 实现了 CommandLineRunner 接口的调用
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try { // args.getSourceArgs() 为string 数组
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
6. 问题
- 启动加载器如何实现?
- 启动加载器实现的异同点?
- 启动加载器的调用时机?