一、事件监听机制
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内置事件
SpringApplicationEvent
和 ApplicationContextEvent
都是 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
来完成。
事件类 | 说明 |
---|---|
ApplicationStartingEvent |
在 Spring Boot 应用程序开始启动时触发,表示应用程序即将开始启动。 |
ApplicationEnvironmentPreparedEvent |
环境变量准备完成,但此时上下文context 还没有创建。在该监听中获取到ConfigurableEnvironment 后可以对配置信息做操作,例如:修改默认的配置信息,增加额外的配置信息等等。 |
ApplicationPreparedEvent |
上下文对象准备完成。spring boot 上下文context 创建完成,但此时spring 中的bean 是没有完全加载完成的。在获取完上下文后,可以将上下文传递出去做一些额外的操作。 |
ApplicationStartedEvent |
应用程序的基本配置已经完成,所有的 bean 已经被实例化,但应用程序可能还没有完全准备好处理请求。在这个事件触发时,应用程序的上下文已经准备好,但可能仍然缺少一些外部资源或其他依赖项。 |
ApplicationReadyEvent |
在应用程序完全启动且 ready 状态时触发。在这个事件触发时,应用程序已经准备好接收请求和处理业务逻辑。所有的外部资源和依赖项都已经初始化完成,并且应用程序已经达到可用状态。 |
ApplicationFailedEvent |
启动异常时执行的事件 |
2、ApplicationContextEvent
ApplicationContextEvent
是一个抽象类,它的具体实现类有以下几种常见的:
ContextRefreshedEvent
:在应用程序上下文刷新时触发,表示应用程序上下文已经初始化完毕,所有的 bean 都已经被加载并初始化完成。ContextStartedEvent
:在应用程序上下文启动时触发,表示应用程序上下文已经准备好被使用。ContextStoppedEvent
:在应用程序上下文停止时触发,表示应用程序上下文将要被关闭。ContextClosedEvent
:在应用程序上下文关闭时触发,表示应用程序上下文已经被关闭。