SpringBoot事件监听机制


一、事件监听机制

Spring 事件监听机制(事件驱动模型),是基于 Java 监听者模式(是观察者模式的另一种形态)。

监听者模式包含了一个监听者 Listener 与之对应的事件 Event,还有一个事件发布者 EventPublish,过程就是 EventPublish 发布一个事件,被监听者捕获到,然后做出相应的处理。事件监听机制,其实从 JDK1.1 开始有的设计模式,其主要的几个基类为 事件源EventObject 、监听者EventListener、发布者(Spring)ApplicationEventPublisher

二、案例

1、事件

事件源: Spring的事件源为ApplicationEvent,继承至JDK提供的EventObject 基类。

public class MyContextEvent extends ApplicationEvent {
    public MyContextEvent(Object source) {
        super(source);
        System.out.println("source message->" + source.toString());
    }
}

2、监听者

(1)实现ApplicationListener

监听者: Spring的监听者为ApplicationListener,继承至JDK提供的EventListener 接口。其实EventListener 中没有任何方法定义,只是作为监听者标识。

// 需要注入到容器中
@Component
public class MyContextListener implements ApplicationListener<MyContextEvent> {
    @Override
    public void onApplicationEvent(@NonNull MyContextEvent event) {
        System.out.println("listener event msg: " + event.getSource());
    }
}

这里我们通过Spring容器的事件发布功能来实现,自动以事件的注册发布及监听。 在spring容器事件中AbstractApplicationContext继承至ConfigurableApplicationContext, ConfigurableApplicationContext类继承至ApplicationContext。IOC容器的核心接口ApplicationContext中继承了,事件发布ApplicationEventPublisher. 其子类AbstractApplicationContext中实现了父接口ApplicationEventPublisher中的publishEvent(ApplicationEvent event)方法。

(2)@EventListener

@Component
public class TestEventListener {
    /**
     * 处理事件
     **/
    @EventListener(WebServerInitializedEvent.class)
    public void onWebServerReady(WebServerInitializedEvent event){

    }
}

3、发布事件

@SpringBootApplication
public class SpringtestApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringtestApplication.class, args);

        // 发布事件
        applicationContext.publishEvent(new MyContextEvent("123"));
    }

}

三、防止事件重复触发

主要因为对于web应用会出现父子容器,这样就会触发两次

@Component
public class TestTask implements ApplicationListener<ContextRefreshedEvent> {

    private volatile AtomicBoolean isInit=new AtomicBoolean(false);

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        //防止重复触发
        if(!isInit.compareAndSet(false,true)) {
            return;
        }
        start();
    }

    private void start() {
        //开启任务
        System.out.println("****-------------------init---------------******");
    }
}

四、SpringBoot内置事件

SpringApplicationEventApplicationContextEvent 都是 Spring 框架中的事件类,用于在应用程序的不同阶段触发事件。它们的区别在于它们所代表的事件的范围和应用场景。

SpringApplicationEvent 是在 Spring Boot 应用程序启动和关闭时触发的事件。它是由 SpringApplication 类在应用程序的生命周期中分发的。这些事件包括应用程序的启动、环境准备、上下文加载、刷新和关闭等。

ApplicationContextEvent 是在 Spring 应用程序上下文的生命周期中触发的事件。它是由 ApplicationContext 类在应用程序上下文的各个阶段分发的。这些事件包括上下文的初始化、刷新、启动和关闭等。

因此,可以说 SpringApplicationEvent 主要与 Spring Boot 的应用程序的生命周期相关,而 ApplicationContextEvent 则与 Spring 应用程序上下文的生命周期相关。

1、SpringApplicationEvent

spring boot中支持的事件类型定在org.springframework.boot.context.event包中,springboot的项目启动加载过程,是通过springboot事件触发器EventPublishingRunListener来完成。

img

事件类 说明
ApplicationStartingEvent 在 Spring Boot 应用程序开始启动时触发,表示应用程序即将开始启动。
ApplicationEnvironmentPreparedEvent 环境变量准备完成,但此时上下文context还没有创建。在该监听中获取到ConfigurableEnvironment后可以对配置信息做操作,例如:修改默认的配置信息,增加额外的配置信息等等。
ApplicationPreparedEvent 上下文对象准备完成。spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。在获取完上下文后,可以将上下文传递出去做一些额外的操作。
ApplicationStartedEvent 应用程序的基本配置已经完成,所有的 bean 已经被实例化,但应用程序可能还没有完全准备好处理请求。在这个事件触发时,应用程序的上下文已经准备好,但可能仍然缺少一些外部资源或其他依赖项。
ApplicationReadyEvent 在应用程序完全启动且 ready 状态时触发。在这个事件触发时,应用程序已经准备好接收请求和处理业务逻辑。所有的外部资源和依赖项都已经初始化完成,并且应用程序已经达到可用状态。
ApplicationFailedEvent 启动异常时执行的事件

2、ApplicationContextEvent

ApplicationContextEvent 是一个抽象类,它的具体实现类有以下几种常见的:

  1. ContextRefreshedEvent:在应用程序上下文刷新时触发,表示应用程序上下文已经初始化完毕,所有的 bean 都已经被加载并初始化完成。
  2. ContextStartedEvent:在应用程序上下文启动时触发,表示应用程序上下文已经准备好被使用。
  3. ContextStoppedEvent:在应用程序上下文停止时触发,表示应用程序上下文将要被关闭。
  4. ContextClosedEvent:在应用程序上下文关闭时触发,表示应用程序上下文已经被关闭。

五、常见事件

1、WebServerInitializedEvent


  目录