【源码】Spring —— ApplicationEvent ApplicationListener ApplicationEventMulticaster
前言
本章节介绍 Spring 中 事件 的相关类
版本
Spring 5.2.x
EventObject
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
// 事件源
protected transient Object source;
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
public Object getSource() {
return source;
}
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
由 JDK 定义的事件类,属性 source
为事件源
ApplicationEvent
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
// 事件发生的时间戳
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
Spring 定义的事件类,继承了 EventObject ,拓展了 timestamp
属性记录事件发生的时间
ApplicationContextEvent
public abstract class ApplicationContextEvent extends ApplicationEvent {
public ApplicationContextEvent(ApplicationContext source) {
super(source);
}
public final ApplicationContext getApplicationContext() {
return (ApplicationContext) getSource();
}
}
Spring容器事件 的抽象基类,相当于在 ApplicationEvent 上包装了一层,其子类即具体的 容器生命周期 事件,包括 ContextClosedEvent ContextRefreshedEvent ContextStoppedEvent ContextStartedEvent
如果是 SpringBoot 工程的话,会看到很多事件,基于监听器做了很多拓展
EventListener
public interface EventListener {
}
JDK 定义的 事件监听 标记接口
ApplicationListener
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
// 事件处理逻辑
void onApplicationEvent(E event);
}
Spring 定义的针对 ApplicationEvent 的监听器,是一个 函数式接口,onApplicationEvent
即对目标事件的处理逻辑
SmartApplicationListener
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
// 是否支持指定 事件类型(Class)
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
// 是否支持指定 事件源类型(Class),默认 true
default boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
@Override
// 优先级,默认最低
default int getOrder() {
return LOWEST_PRECEDENCE;
}
}
SmartApplicationListener 继承了 ApplicationListener,提供对 事件类型(基于Class)、事件源类型(基于Class) 的匹配
GenericApplicationListener
public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
// 是否支持指定 事件类型(Class)
boolean supportsEventType(ResolvableType eventType);
// 是否支持指定 事件源类型(Class),默认 true
default boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
@Override
// 优先级,默认最低
default int getOrder() {
return LOWEST_PRECEDENCE;
}
}
GenericApplicationListener 继承了 ApplicationListener,提供对 事件类型(基于ResolvableType)、事件源类型(基于Class) 的匹配
关于 ResolvableType,可以阅读下面文章
GenericApplicationListenerAdapter
SmartApplicationListener 和 GenericApplicationListener 的适配器,即通过 Class 和 ResolvableType 的转换将两者连接起来
ApplicationEventMulticaster
public interface ApplicationEventMulticaster {
// 监听器添加
void addApplicationListener(ApplicationListener<?> listener);
// 监听器 beanName 添加
void addApplicationListenerBean(String listenerBeanName);
// 监听器移除
void removeApplicationListener(ApplicationListener<?> listener);
// 监听器 beanName 移除
void removeApplicationListenerBean(String listenerBeanName);
// 移除所有监听器
void removeAllListeners();
// 事件发布
void multicastEvent(ApplicationEvent event);
// 指定类型的事件发布
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
ApplicationEventMulticaster,事件组播顶层接口
- 它是一个事件发布类,提供事件发布方法
multicastEvent
- 同时也是一个监听器管理类,提供监听器的注册、移除相关方法
AbstractApplicationEventMulticaster
ApplicationEventMulticaster 的核心抽象类,主要实现了 监听器管理
的相关方法,它的实现也是比较经典的 Spring
式实现,不贴过多源码,此处做个概括:
- 所有的
监听器
是由内部类DefaultListenerRetriever
来负责管理的 - 基于事件源、事件类型和对应的 监听器 由一个缓存集合管理,
key
为内部类ListenerCacheKey
,对应监听器集合由内部类CachedListenerRetriever
管理 - 因此监听器的注册、移除操作委托给
DefaultListenerRetriever
- 监听器的注册方法有
addApplicationListener
和addApplicationListenerBean
,前者直接注册对应的监听器
,后者是注册一个 监听器 的beanName
,需要时直接从容器
获取 - 监听器的获取基于
缓存
实现
之所以说是经典的 Spring 式实现,是因为这种管理类的实现模式在 Spring 很常用且很实用
基于内部类和缓存,可以高效地管理比较复杂的内部对象
与之相似的还有 GenericConversionService 的实现
SimpleApplicationEventMulticaster
AbstractApplicationEventMulticaster 的实现类,主要实现事件发布方法
- 主要逻辑简单清晰,根据
事件源、事件类型
基于AbstractApplicationEventMulticaster
的实现获取对应的监听器,回调对应 监听器 方法即可 - 它支持基于
多线程
的调用,只要初始化是传入对应自行构造的线程池
即可,如果不传,则默认当前线程发布事件
demo
public class AEvent extends ApplicationContextEvent {
public AEvent(ApplicationContext source) {
super(source);
}
}
public class BEvent extends ApplicationContextEvent {
public BEvent(ApplicationContext source) {
super(source);
}
}
自定义两个事件 AEvent
BEvent
public class AListener implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return AEvent.class.isAssignableFrom(eventType);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("AListener detect a AEvent");
}
}
public class BListener implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return BEvent.class.isAssignableFrom(eventType);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("BListener detect a BEvent");
}
}
针对上述事件分别定义两个监听器 AListener
BListener
@Configuration
public class Config {
@Bean
public BListener bListener() {
return new BListener();
}
}
通过配置类把 BListener
注册为 bean
,AListener
我们打算通过 addApplicationListener
方法注册进去
@SpringBootTest
@ContextConfiguration(classes = Config.class)
public class TestMain {
@Autowired
BeanFactory beanFactory;
@Autowired
ApplicationContext applicationContext;
@Test
public void test() {
SimpleApplicationEventMulticaster applicationEventMulticaster
= new SimpleApplicationEventMulticaster(beanFactory);
applicationEventMulticaster.addApplicationListener(new AListener());
applicationEventMulticaster.addApplicationListenerBean("bListener");
applicationEventMulticaster.multicastEvent(new AEvent(applicationContext));
applicationEventMulticaster.multicastEvent(new BEvent(applicationContext));
}
}
测试类如上:
- 通过
addApplicationListener
方法注册AListener
- 通过
addApplicationListenerBean
方法把名称为bListener
的监听器bean
注册进去 - 分别发布事件
AEvent
BEvent
,结果就是各自监听对应的事件
总结
本章节介绍了 Spring 下定义的事件相关接口 ApplicationEvent ApplicationListener ApplicationEventMulticaster,在 Spring容器 中注册的 发布事件类 其实就是 SimpleApplicationEventMulticaster