在众多的Spring教学视频中,很少有课程去讲解SpringEvent相关功能使用的。或许是比较简单吧。引发对Event功能探究的原因是最近在看PIG开源项目,发现其中认证模块多处使用到了SpringEvent的功能。于是,准备翻翻官方文档做一个学习笔记。
1.简介
在ApplictionContext中的事件发布和处理的操作,是由ApplictionEvent和ApplictionListener两个接口来实现的。当一个Bean实现了ApplictionListener并加入了容器。当一个ApplictionEvent发布到容器后,这个Bean就可以自动地获取到这个Event并进行处理。这是典型的观察者模式(Observer Pattern)
对于ApplictionEvent,Spring框架帮我们内置了好多:
- ContextRefreshedEvent
- ContextStartedEvent
- ContextStoppedEvent
2.自定义事件发布和获取
2.1自定义一个事件
- 类extends
ApplicationEvent
官方实例:
@Datapublic class BlockedListEvent extends ApplicationEvent {private final String address;private final String content;public BlockedListEvent(Object source, String address, String content) {super(source);this.address = address;this.content = content;}// accessor and other methods...}
2.2创建事件发布者
事件的发布需要使用Spring提供的ApplicationEventPublisher来发布。或者通过ApplicationContext也可以发布
@Componentpublic class EmailService implements ApplicationEventPublisherAware {private ApplicationEventPublisher publisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher publisher) {this.publisher = publisher;}public void sendEmail(String address, String content) {//发布事件publisher.publishEvent(new BlockedListEvent(this, address, content));}}
2.3创建监听者
监听者可以获取到事件对象。具体的实现方式如下:
@Componentpublic class BlockedListNotifier implements ApplicationListener<BlockedListEvent> {private String notificationAddress;public void setNotificationAddress(String notificationAddress) {this.notificationAddress = notificationAddress;}@SneakyThrows@Overridepublic void onApplicationEvent(BlockedListEvent event) {System.err.println("接收消息");Thread.sleep(5000);System.out.println(event);// notify appropriate parties via notificationAddress...}}
2.4注意事项
- 同一类Event,在上一个没有处理完成时。永远不允许发送第二个
- 监听者的消费顺序是一个一个来的,不是并发
-
3.使用注解方式注册监听器
在前面我们注册一个监听者需要写一个类,如果要监听多个事件就要有多个类对象,但是大多数情况下可能逻辑就是记录个日志,所以注解方式可以实现一个Bean写多个方法处理不同的事件。每个方法处理一类或多类事件。
@EventListener```java @Component public class MyListener { @EventListener public void commence(BlockedListEvent event){ System.err.println(“注解方式处理”); System.err.println(event);}
}
此外注解里值还可以对事件进行过滤和处理完后也发事件。具体内容用到时再仔细看一下。具体功能有:1. 通过事件对象中的字段过滤2. 处理完事件后,也发布一个事件<a name="xpfTz"></a># 4.异步监听器异步监听器没啥特别的,就是在方法上添加一个`@Async`注解```java@EventListener@Asyncpublic void processBlockedListEvent(BlockedListEvent event) {// BlockedListEvent is processed in a separate thread}
5.顺序监听器
不用说吧,@Order注解来解决
@EventListener@Order(42)public void processBlockedListEvent(BlockedListEvent event) {// notify appropriate parties via notificationAddress...}
6.通用事件类型
在2节中,我们通过实现ApplicationEvent来定义自己的事件,但是其实我们的事件可能就是我们的一个实体类。于是乎,Spring提供了一个EntityCreatedEvent<T>。T就是指定我们自己定义的实体类即可。
注:这个功能我没有实验出来,因为我没有这个类。不知道为啥。
