Spring Boot启动流程扩展

Spring Boot启动可扩展流程

通过上一篇Spring Boot启动流程详解,我们可知Spring Boot在以下几点可以进行扩展

  1. 初始化器(Initializer)
  2. 监听器(Listener)
  3. 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可以看到如下输出

总共监听到了以下事件

  1. ApplicationEnvironmentPreparedEvent
  2. ApplicationContextInitializedEvent
  3. ApplicationPreparedEvent
  4. ApplicationStartedEvent
  5. ApplicationReadyEvent

而没有监听到的事件是ApplicationStartingEvent,这是因为在发送此事件时,日志对象还没有初始化成功,所有无法打印日志,如果使用System.out.println则可以看到输出

Runner

Runner的实现分为两种

  1. ApplicationRunner
  2. 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可以看到如下输出

总结

  1. Initializer需要实现ApplicationContextInitializer接口
  2. Listener需要实现ApplicationListener
  3. Initializer和Listener可以在META-INF/spring.factories进行配置,以便Spring Boot加载
  4. Runner有ApplicationRunner和CommandLineRunner两种实现,两者除了接收参数不同外(一个接收ApplicationArguments,一个接收String[]),没有其他的区别
  5. @Order注解用来决定Runner的执行顺序

参考文献


Reprint please specify: wbl Spring Boot启动流程扩展

Previous
git rebase,reset以及revert命令分析 git rebase,reset以及revert命令分析
基本概念在讲述命令的使用姿势之前,我们首先需要了解git仓库的组成。git仓库主要由三部分组成,分别是工作空间(workspace), 暂存区(stage), 本地仓库。 工作空间(workspace): 通过git进行版本管理的目录和文
2019-05-03
Next
Spring Boot启动流程初探 Spring Boot启动流程初探
刚接触Spring Boot的时候,相信大家都有接触过以下代码,这是Spring Boot的启动类,今天就来简单看下Spring Boot的启动流程 @SpringBootApplication public class Applicati
2019-04-27