Spring Boot启动可扩展流程
通过上一篇Spring Boot启动流程详解,我们可知Spring Boot在以下几点可以进行扩展
- 初始化器(Initializer)
- 监听器(Listener)
- Runners
下面依次来看下如何添加扩展
Initializer
Spring Boot在启动时会从META-INF/spring.factories文件中,加载ApplicationContextInitializer,下面是其定义
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(ConfigurableApplicationContext configurableApplicationContext);
}
下面,我们定义一个类来实现该接口
@Slf4j
public class CustomApplicationInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
log.info("自定义Initializer启动");
}
}
加载自定义的initializer的方式有两种,一是在main方法中add initializer另一种则更符合Spring Boot style,在META-INF/spring.factories中增加自定义initializer的配置
org.springframework.context.ApplicationContextInitializer=com.wbl.spingbootdemo.initializer.CustomApplicationInitializer
启动Spring Boot则可以看到如下输出
Listener
Spring Boot启动的时候会从META-INF/spring.factories文件中加载ApplicationListener,
下面是其定义
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(ApplicationEvent applicationEvent;
}
ApplicationListener实现了EventListener接口,这是JDK中定义的一个类,用来实现观察者模式。只不过ApplicationListener只监听ApplicationEvent事件
下面实现一个自定的ApplicationListener,监听的几个事件都是继承SpringApplicationEvent的
@Slf4j
public class CustomApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
if (applicationEvent instanceof ApplicationStartingEvent){
log.info("receive application starting event");
}
if (applicationEvent instanceof ApplicationStartedEvent){
log.info("receive application started event");
}
if (applicationEvent instanceof ApplicationEnvironmentPreparedEvent) {
log.info("receive application environment prepared event");
}
if (applicationEvent instanceof ApplicationPreparedEvent){
log.info("receive application application prepared event");
}
if (applicationEvent instanceof ApplicationContextInitializedEvent){
log.info("receive application context initialized event");
}
if (applicationEvent instanceof ApplicationReadyEvent){
log.info("receive application ready event");
}
}
}
启动Spring Boot可以看到如下输出
总共监听到了以下事件
- ApplicationEnvironmentPreparedEvent
- ApplicationContextInitializedEvent
- ApplicationPreparedEvent
- ApplicationStartedEvent
- ApplicationReadyEvent
而没有监听到的事件是ApplicationStartingEvent,这是因为在发送此事件时,日志对象还没有初始化成功,所有无法打印日志,如果使用System.out.println则可以看到输出
Runner
Runner的实现分为两种
- ApplicationRunner
- CommandLineRunner
这两个实现本质上没有什么不同,除了接收参数不同
ApplicationRunner
下面实现了一个自定义的ApplicationRunner
@Service
@Slf4j
@Order(1)
public class CustomApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("启动自定义ApplicationRunner");
}
}
@Order用来决定Runner执行的顺序,数字越小,表示优先级越高,越先执行
CommandLineRunner
下面实现一个自定义的CommandLineRunner
@Service
@Slf4j
@Order(2)
public class CustomCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.info("启动自定义CommandLineRunner");
}
}
启动两个Runner可以看到如下输出
总结
- Initializer需要实现ApplicationContextInitializer接口
- Listener需要实现ApplicationListener
- Initializer和Listener可以在META-INF/spring.factories进行配置,以便Spring Boot加载
- Runner有ApplicationRunner和CommandLineRunner两种实现,两者除了接收参数不同外(一个接收ApplicationArguments,一个接收String[]),没有其他的区别
- @Order注解用来决定Runner的执行顺序