目录
3.ApplicationEventPublisherAware
2.自定义事件发布工具MyPublishAware.java
3.自定义两个事件监听器MyListenner.java(实现接口方式)和MyListennerTwo.java(注解方式)
概念
事件的发布者发布事件,事件的监听者对对应的事件进行监听,当监听到对应的事件时,就会触发调用相关的方法。因此,在事件处理中,事件是核心,是事件发布者和事件监听者的桥梁。
Spring 是基于Observer模式(java.util包中有对应实现)提供了针对Bean的事件发布和订阅功能。
Spring中相关的主要有3个接口和1个抽象类:
public abstract class ApplicationEvent extends EventObject{ public interface ApplicationEventPublisher{ public interface ApplicationEventPublisherAware extends Aware{ public interface ApplicationListener<E extends ApplicationEvent> extends EventListener{
1.ApplicationEvent
ApplicationEvent继承自JavaSE中的EventObject,我们在使用的时候可以继承这个抽象类来定义事件,进行信息的传递,因为ApplicationListener只接受ApplicationEvent或者他的子类。
Spring自定义的ApplicationEvent实现类有很多:
其中:
Spring提供5种标准的事件监听:
上下文更新事件(ContextRefreshedEvent):
该事件会在ApplicationContext被初始化或者更新时发布。
也可以在调用ConfigurableApplicationContext接口中的refresh()方法时被触发。
上下文开始事件(ContextStartedEvent):
当容器ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
上下文停止事件(ContextStoppedEvent):
当容ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
上下文关闭事件(ContextClosedEvent):
当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
请求处理事件(RequestHandledEvent):
在Web应用中,当一个http请求(request)结束触发该事件。
Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:
ApplicationStartedEvent :
spring boot启动开始时执行的事件
ApplicationEnvironmentPreparedEvent:
spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
ApplicationPreparedEvent:
spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
ApplicationFailedEvent:
spring boot启动异常时执行事件
2.ApplicationEventPublisher
事件的发布接口,通过publishEvent(ApplicationEvent event)方法来发布消息。
3.ApplicationEventPublisherAware
通过这个接口的void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)方法,将ApplicationEventPublisher注入进去,来进行消息通知。
4.ApplicationListener
监听器接口,ApplicationListener中的void onApplicationEvent(E event)来接收消息事件,进行消息处理。通过源代码发现,事件E需要是ApplicationEvent或者ApplicationEvent的子类。
具体使用
1.自定义事件MyEvent.java
package com.genertech.plm.aia.portaladmin.test;
import org.springframework.context.ApplicationEvent;
/**
* @author: huo.qw
* @createTime: 2024/01/16 下午 08:17
* @description:
* @version: v1.0
*/
public class MyEvent extends ApplicationEvent {
// 也可以是对象等其它数据,也可以不传递数据
private String words;
public MyEvent(Object source, String words) {
super(source);
this.words = words;
}
public String getWords() {
return words;
}
public void setWords(String words) {
this.words = words;
}
}
2.自定义事件发布工具MyPublishAware.java
// 不支持异步,sayHello()发布事件后会等待所有监听器执行完(多个监听器之间也是串行执行的)才会继续执行sayHello()以下的代码。
// 若要支持,可以在启动类加@EnableAsync,在监听器的onApplicationEvent方法、
// 或者@EventListener(MyEvent.class)标注的方法加@Async注解实现。
package com.genertech.plm.aia.portaladmin.test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author: huo.qw
* @createTime: 2024/01/16 下午 08:33
* @description:
* @version: v1.0
*/
@Component
@EnableScheduling // 开启定时任务
@Slf4j
public class MyPublishAware implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void sayHello(MyEvent myEvent) {
this.applicationEventPublisher.publishEvent(myEvent);
}
// 通过定时任务来测试[发布事件]
@Scheduled(fixedRate = 10000 * 1)
public void tryTest() {
MyEvent myEvent = new MyEvent(this, new String("hello World!"));
sayHello(myEvent);
// 不支持异步,sayHello()发布事件后会等待所有监听器执行完(多个监听器之间也是串行执行的)才会继续执行sayHello()以下的代码。
// 若要支持,可以在启动类加@EnableAsync,在监听器的onApplicationEvent方法、
// 或者@EventListener(MyEvent.class)标注的方法加@Async注解实现。
log.info(Thread.currentThread().getName()+"测试是否支持异步");
}
}
3.自定义两个事件监听器MyListenner.java(实现接口方式)和MyListennerTwo.java(注解方式)
package com.genertech.plm.aia.portaladmin.test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @author: huo.qw
* @createTime: 2024/01/16 下午 08:34
* @description:
* @version: v1.0
*/
@Component
@Slf4j
public class MyListenner implements ApplicationListener<MyEvent> {
//如果实现的是implements ApplicationListener<ApplicationEvent>,则
//public void onApplicationEvent(ApplicationEvent e) {会监听到所有
//继承了ApplicationEvent抽象类的事件,其中包括MyEvent事件.
@Override
//@EventListener(MyEvent.class)
public void onApplicationEvent(MyEvent e) {
log.info(Thread.currentThread().getName()+"MyListennerOne订阅接收到的数据为:" + e.getWords());
try {
Thread.sleep(5000L);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
package com.genertech.plm.aia.portaladmin.test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* @author: huo.qw
* @createTime: 2024/01/17 下午 03:39
* @description:
* @version: v1.0
*/
@Component
@Slf4j
public class MyListennerTwo {
@EventListener(MyEvent.class)
public void methodName(MyEvent e) {
log.info(Thread.currentThread().getName()+"MyListennerTwo订阅接收到的数据为:" + e.getWords());
try {
Thread.sleep(5000L);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
参考文章
Spring 事件发布订阅_spring事件发布订阅-CSDN博客
spring中的发布订阅_spring 订阅发布-CSDN博客
Spring Event事件用法 Spring Boot Event事件发布和订阅 Spring Event事件发布 Spring Event事件订阅_springboot 事件发布订阅-CSDN博客