Spring监听器不同的注册方式下带来的监听范围的变化

事件监听注册的几种方式

ApplicationContext下面简称AC

1.构建SpringApplication时注册(可以监听AC启动阶段事件)

// 方式一:
//写法1
SpringApplication application = new SpringApplicationBuilder().listeners(new ApplicationPidFileWriter()).build(args);
//写法2
SpringApplication springApplication = new SpringApplication();
        application.addListeners(new ApplicationPidFileWriter());

2.在META-INF/spring.factories中注册(可以监听AC启动阶段事件)

org.springframework.context.ApplicationListener=org.springframework.boot.context.ApplicationPidFileWriter

3.bean扫描(部分AC启动阶段事件无法监听)

@Component
public class ApplicationAvailabilityExporter {

    @EventListener
    public void onStateChange(AvailabilityChangeEvent event) {
        AvailabilityState state = event.getState();
        if (state.equals(ReadinessState.ACCEPTING_TRAFFIC)) {
            System.out.println("应用程序已经可以接受外部请求");
        } else if (state.equals(ReadinessState.REFUSING_TRAFFIC)) {
            System.out.println("应用程序拒绝接受外部请求");
        } else if (state.equals(LivenessState.BROKEN)) {
            System.out.println("应用程序不可用");
        } else if (state.equals(LivenessState.CORRECT)) {
            System.out.println("应用程序正常");
        }
    }
}

监听时机问题

springboot里面有部分事件是在ApplicationContext创建之前发布的。所以这就有有了上面的前两种注册方式,第三种注册方式,是我们最常见,也是业务中最常用的一种方式。

比如:

ApplicationStartingEvent 在SpringApplication的run方法内,它发布的时间会很早,在SpringApplicationRunListeners里面就包含着通过方法一和方法二注册的监听器,但是这个时候不包含第三种。
在这里插入图片描述
在这里插入图片描述

监听器注册演示

@SpringBootApplication
public class Study03Application {

    public static void main(String[] args) {
        try {
            SpringApplication application = new SpringApplicationBuilder(Study03Application.class)
                    .bannerMode(Banner.Mode.OFF)
                    // 指定web应用程序类型,SERVLET,REACTIVE,NONE
                    // NONE  就是表示不对外提供web服务
                    .web(WebApplicationType.SERVLET)
                    .allowCircularReferences(true) // 是否允许循环引用
                    .build();
            // ApplicationListener 分为两种,一种是在spring容器初始化完成之前就需要监听事件的,一种是在spring容器初始化完成之后监听事件的
            // 第一种比如: 应用程序的pid写入文件,当程序启动后spring会发送ApplicationPreparedEvent事件,但是这个时候,spring还没有扫描所有组件进行初始化。
            // 这个时候就无法监听
            //application.addListeners(new ApplicationPidFileWriter());
            application.addListeners(new WebServerPortFileWriter());
            // 第二种是比较常见的,这里就不演示了
            application.run(args);
        } catch (Exception ex){
            ex.printStackTrace();
        }
}

在resources目录下的META-INF/spring.factories中添加下面内容

org.springframework.context.ApplicationListener=org.springframework.boot.context.ApplicationPidFileWriter

启动后会自动生成这两个内容
在这里插入图片描述

ApplicationContext初始化过程中发布的事件

  1. ApplicationStartingEvent是在DefaultBootstrapContextSpringApplicationRunListeners刚初始化完
    在这里插入图片描述

  2. ApplicationEnvironmentPreparedEvent是在环境信息初始化完成
    在这里插入图片描述

  3. ApplicationContextInitializedEvent是在ApplicationContext初始化完成之后

在这里插入图片描述

  1. ApplicationPreparedEvent 在refresh之前,在bean声明被加载之后。
  2. ApplicationStartedEvent 在ac的refresh之后,在ApplicationRunner和CommandRunner之前发布
  3. AvailabilityChangeEvent 在started之后发布
  4. ApplicationReadyEvent 是在ApplicationRunner和CommandRunner之后执行
  5. AvailabilityChangeEvent 是在ready之后执行
  6. ApplicationFailedEvent 是在应用应用程序启动失败时发布
  7. WebServerInitializedEvent 在WebServer准备好后发布
  8. ContextRefreshedEvent 是在AC的refresh执行完成后

基于spring事件驱动机制下,存在多个ApplicationContext的情况下,子AC发送的消息会被传递到父AC中。

在多层级下的ApplicationContext,一个监听器可能收到多个同样的事件,这就是因为事件向父类传递导致的,由此衍伸出,可以通过实现ApplicationContextAwre或者@Autowire 来注入AC进行区分是子类的AC传递过来的还是父AC传递过来的

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值