文章目录
Spring事件监听机制
Spring事件监听机制概述
Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式;为的就是业务系统逻辑的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。
在Spring中我们可以通过实现ApplicationListener接口或者@EventListener接口来实现事件驱动编程。
比如我们做一个电商系统,用户下单支付成功后,我们一般要发短信或者邮箱给用户提示什么的,这时候就可以把这个通知业务做成一个单独事件监听,等待通知就可以了;把它解耦处理。

Spring事件监听机制介绍
Spring事件相关的几个类
| Spring事件类 | 自定义类 | 描述 |
|---|---|---|
| org.springframework.context.ApplicationContext | 运行程序上下文 | |
| org.springframework.context.ApplicationListener | AbstractEventListener | 事件监听器接口 |
| org.springframework.context.ApplicationEvent | AbstractEvent | 事件对象的父类 |
| org.springframework.context.event.ApplicationEventMulticaster | 发布事件的接口 | |
| org.springframework.context.event.SimpleApplicationEventMulticaster | 发布事件的简单实现类 |
使用硬编码简单还原Spring事件机制
-
自定义事件,需要继承
ApplicationEvent类 -
自定义事件监听器,需要实现
ApplicationListener接口,这个接口有个方法onApplicationEvent需要实现,用来处理相关的事件。public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); } -
创建事件广播器
创建事件广播器
ApplicationEventMulticaster,这是个接口,你可以自己实现这个接口,也可以直接使用系统给我们提供的SimpleApplicationEventMulticaster,如下:ApplicationEventMulticaster applicationEventMulticaster = new SimpleApplicationEventMulticaster(); -
向广播器中注册事件监听器
将事件监听器注册到广播器
ApplicationEventMulticaster中,如:ApplicationEventMulticaster applicationEventMulticaster = new SimpleApplicationEventMulticaster(); applicationEventMulticaster.addApplicationListener(new SendEmailOnOrderCreateListener()); -
通过广播器发布事件
广播事件,调用
ApplicationEventMulticaster#multicastEvent方法广播事件,此时广播器中对这个事件感兴趣的监听器会处理这个事件。applicationEventMulticaster.multicastEvent(new OrderCreateEvent(applicationEventMulticaster, 1shiL));
Spring事件机制正确的使用方式
Spring事件创建
创建一个抽象接口AbstractEventListener,继承ApplicationListener 接口
public abstract class AbstractEvent extends ApplicationEvent {
public AbstractEvent(Object source) {
super(source);
}
}
创建自定义事件类TestEvent
@Getter
public class TestEvent extends AbstractEvent{
private Integer test;
public TestEvent(Object source, Integer test) {
super(source);
this.test = test;
}
}
Spring事件发布方式
-
第一种方式:实现
ApplicationEventPublisherAware接口,如果是老项目改动比较大,不建议使用。通常情况下,我们会使用以
ApplicationContext结尾的类作为Spring的容器来启动应用

说明了`AbstractApplicationContext`内部已经集成了事件广播器`ApplicationEventMulticaster`,说明`AbstractApplicationContext`内部是具体事件相关功能的,这些功能是通过其内部的`ApplicationEventMulticaster`来实现的,也就是说将事件的功能委托给了内部的`ApplicationEventMulticaster`来实现。
### ApplicationEventPublisher接口
上面类图中多了一个新的接口`ApplicationEventPublisher`,来看一下源码
```java
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
```
这个接口用来发布事件的,内部定义2个方法都是用来发布事件的。
### 获取ApplicationEventPublisher对象
如果我们想在普通的bean中获取`ApplicationEventPublisher`对象,需要实现`ApplicationEventPublisherAware`接口
```java
public interface ApplicationEventPublisherAware extends Aware {
void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);
}
```
Spring容器会自动通过上面的`setApplicationEventPublisher`方法将`ApplicationEventPublisher`注入进来,此时我们就可以使用这个来发布事件了。
-
第二种方式:使用Spring容器中
ApplicationContext容器。建议使用。在Spring中的**
ApplicationContext容器支持对事件的发布,本质和第一种方式一样,因为ApplicationContext接口继承ApplicationEventPublisher进行发布事件的。**/** * 异步事件发送 * * @author Java技术债务 * @date 2021/2/5 */ @Service public class EventPublisher { @Autowired private ApplicationContext applicationContext; /** * 发送异步事件 * * @param event e */ public void publishEvent(ApplicationEvent event) { applicationContext.publishEvent(event); } }原理:无论哪种方式最终都是由
ApplicationEventMulticaster接口的实现类SimpleApplicationEventMulticaster进行发布并执行事件。public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { ... ... @Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event);

最低0.47元/天 解锁文章
269

被折叠的 条评论
为什么被折叠?



