springboot(2)生命周期和监听器

Spring boot应用,这里具体的来说,是指类SpringApplication,在其run()方法运行过程中,主要围绕所使用ApplicationContext对象的生命周期事件,应用了一个事件监听器机制提供了相应的程序扩展入口点,开发人员可以基于此机制,在相应的事件发生时执行特定的逻辑。

SpringApplication应用的该事件监听器机制主要利用如下两个类/接口 :

SpringApplicationRunListeners

SpringApplicationRunListener

简单来讲,在SpringApplication的run()方法执行时,应用上下文ApplicationContext对象创建之前,应用程序会首先找到配置中所定义的所有SpringApplicationRunListener的实现类(这些实现类可能由Spring boot自身实现和提供,也可以由开发人员来实现和提供),创建他们的实例,然后把它们放在一个集合中,然后封装为一个 SpringApplicationRunListeners 实例。之后Spring boot应用开始创建ApplicationContext对象,然后在相应的ApplicationContext的生命周期事件发生时,程序会通过该SpringApplicationRunListeners 实例向各个 SpringApplicationRunListener 实例广播相应的事件,从而SpringApplicationRunListener 实现类中相应的监听器逻辑得到执行。

这里所提到的SpringApplicationContext的生命周期事件,具体来讲,是如下事件 :

发生顺序事件事件类型备注
1startingApplicationStartedEvent系统刚启动
2environmentPreparedApplicationEnvironmentPreparedEvent环境已经准备好,但是ApplicationContext实例尚未被创建
3contextPrepared ApplicationContext已经被创建并且准备就绪,但是sources尚未被加载
4contextLoadedApplicationPreparedEventApplicationContext实例的sources已经被加载,但是ApplicationContext实例尚未被刷新(refresh)
5finishedApplicationFailedEvent
ApplicationReadyEvent
Spring应用程序启动完成时发送该事件,此时ApplicationContext实例已经成功创建完成,或者遇到异常创建失败。对于该ApplicationContext是一个WebApplicationContext的情况,此时内置的Web容器已经在其他线程启动处于服务就绪状态,而SpringApplication执行主线程已经完成自己的
任务。

 

SpringApplication.run()方法中事件监听有关逻辑

// SpringApplication 类
public ConfigurableApplicationContext run(String... args) {
     StopWatch stopWatch = new StopWatch();
     stopWatch.start();
     ConfigurableApplicationContext context = null;
     FailureAnalyzers analyzers = null;
     configureHeadlessProperty();
     // 从配置中获取SpringApplicationRunListener实现类并实例化,
     // 最终把所有这些实例包装到一个SpringApplicationRunListeners实例来使用
     SpringApplicationRunListeners listeners = getRunListeners(args);
     // 启动各个SpringApplicationRunListener 监听器实例 
     listeners.starting();
     try {
          ApplicationArguments applicationArguments = 
               new DefaultApplicationArguments(args);
          // 准备环境
          // 结束时会向各个SpringApplicationRunListener发送事件 
          // environmentPrepared     
          ConfigurableEnvironment environment = 
               prepareEnvironment(listeners,applicationArguments);
          Banner printedBanner = printBanner(environment);
          context = createApplicationContext();// 这里创建应用上下文
          analyzers = new FailureAnalyzers(context);
         // 准备应用上下文,
         // 完成时会向各个SpringApplicationRunListener发送事件 
         // contextPrepared
         prepareContext(context, environment, listeners, 
                applicationArguments,printedBanner);
         refreshContext(context);
         afterRefresh(context, applicationArguments);
        // 应用上下文准备完成
        // 向各个SpringApplicationRunListener发送事件 
        // finished
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
             new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
         }
         return context;
     }catch (Throwable ex) {
        // 应用上下文准备遇到异常时,
       // 向各个SpringApplicationRunListener发送事件finished,
       // 携带响应异常信息
       handleRunFailure(context, listeners, analyzers, ex);
       throw new IllegalStateException(ex);
     }
}

读取监听配置并进行实例化:

SpringApplicationRunListeners类主要是将一组SpringApplicationRunListener聚合到一起,然后使用统一的方式传播事件。

其实现逻辑如下,主要就是将事件传播到各个SpringApplicationRunListener实例。

EventPublishingRunListener是springboot的默认事件监听器,源码如下:

具体的事件传播过程如下:

遍历所有ApplicationListener,并调用invokeListener方法。

注意:springboot在广播事件的时候,默认是同步的,如果想要实现事件异步传播,需要进行如下配置:

这样,在执行getTaskExecutor方法时,才能获取到线程池,才能从线程池中获取空闲线程进行回调。还可以设置ErrorHandler,在出现异常时进行回调。

上述几个监听器类关系如下图所示:

一般在系统中,如果需要监听springboot的生命周期,比如在启动完成后需要进行相关数据初始化,更好的办法是实现ApplicationListener监听器,而不是SpringApplicationRunListener监听器。

ApplicationListener监听编程实例:

假设我需要在系统启动时,执行某些操作,代码如下:

更一般的实例:

假设在用户注册成功后,需要向用户发送短信、邮件、积分等信息时,也可以使用springboot的事件监听,代码如下:

 

springboot进行事件监听有四种实现方式:

1.手工向ApplicationContext中添加监听器

在main方法中,application.addApplicationListener(new MyListener());

2.将监听器装载入spring容器

直接在监听器类上加入@Component

3.在application.properties中配置监听器

application.properties中配置监听,context.listener.classes = com.listener.MyListener

4.通过@EventListener注解实现事件监听

创建自定义监听类,该类无需实现ApplicationListener接口,使用@EventListener注解修饰某个方法,那么这个方法就实现了接口ApplicationListener的onApplicationEvent方法功能。

根据调试,发现SpringBoot四种事件的实现方式监听是有序的,顺序为:3、4、2、1

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值