Appearance
事件通知机制
一、核心组件概述
Spring事件机制遵循观察者模式(Observer Pattern),核心组件包括:
- 事件(Event):继承
ApplicationEvent
的对象,代表发生的具体事件(如容器刷新、Bean初始化完成等)。 - 监听者(Listener):实现
ApplicationListener
接口或使用@EventListener
注解的方法,负责处理事件。 - 发布者(Publisher):实现
ApplicationEventPublisher
接口的对象(通常由ApplicationContext
担任),负责发布事件。 - 多播器(Multicaster):实现
ApplicationEventMulticaster
接口的对象(默认是SimpleApplicationEventMulticaster
),负责将事件转发给所有符合条件的监听者,是事件机制的调度中心。
二、事件机制的初始化流程
事件机制的初始化伴随ApplicationContext
的启动(refresh()
方法),主要分为两步:初始化多播器和注册监听者。
1. 初始化多播器(initApplicationEventMulticaster)
AbstractApplicationContext
的refresh()
方法中,会调用initApplicationEventMulticaster()
初始化多播器:
java
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 1. 优先使用容器中自定义的多播器(bean名称必须为"applicationEventMulticaster")
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
// 2. 否则使用默认的SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
- 关键逻辑:
- 若容器中存在名为
applicationEventMulticaster
的ApplicationEventMulticaster
bean,优先使用它(自定义多播器)。 - 否则创建默认的
SimpleApplicationEventMulticaster
,并注册为单例bean。
- 若容器中存在名为
2. 注册监听者(registerListeners)
refresh()
方法中,接着调用registerListeners()
注册所有监听者:
java
protected void registerListeners() {
// 1. 注册静态监听者(通过addApplicationListener()手动添加的)
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 2. 注册容器中所有实现ApplicationListener接口的bean(通过bean名称注册,避免提前初始化)
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 3. 处理早期事件(多播器初始化前发布的事件,暂存于earlyApplicationEvents)
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
- 关键逻辑:
- 静态监听者:通过
ApplicationContext.addApplicationListener()
手动添加的监听者,直接注册到多播器。 - 动态监听者:容器中所有实现
ApplicationListener
接口的bean,通过addApplicationListenerBean()
注册(仅注册bean名称,待事件发布时才初始化bean)。 - 早期事件:若在多播器初始化前发布事件(如
BeanFactoryPostProcessor
执行时),会暂存于earlyApplicationEvents
,待多播器初始化后再处理。
- 静态监听者:通过
三、事件发布与传播流程
事件发布的入口是ApplicationContext.publishEvent()
方法,底层通过多播器将事件转发给监听者。
1. 事件发布(publishEvent)
AbstractApplicationContext
的publishEvent()
方法负责发布事件:
java
@Override
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// 1. 将事件包装为ApplicationEvent(若不是的话)
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
// 非ApplicationEvent的对象,用PayloadApplicationEvent包装(携带事件源)
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// 2. 处理早期事件(多播器未初始化时,暂存)
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
// 3. 调用多播器转发事件
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// 4. 向父容器发布事件(若有父容器)
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
- 关键逻辑:
- 事件包装:非
ApplicationEvent
的对象会被包装为PayloadApplicationEvent
(携带事件源ApplicationContext
)。 - 早期事件处理:若多播器未初始化(如
refresh()
前),事件暂存于earlyApplicationEvents
。 - 多播器转发:调用多播器的
multicastEvent()
方法转发事件。 - 父容器传播:事件会向父容器递归发布(若有父容器)。
- 事件包装:非
2. 事件多播(multicastEvent)
SimpleApplicationEventMulticaster
的multicastEvent()
方法是事件传播的核心,负责将事件转发给所有符合条件的监听者:
java
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 1. 获取符合条件的监听者(过滤、排序)
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 2. 异步执行(若配置了Executor)
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
} else {
// 3. 同步执行(默认)
invokeListener(listener, event);
}
}
}
- 关键逻辑:
- 事件类型解析:通过
ResolvableType
解析事件的具体类型(如ContextRefreshedEvent
)。 - 监听者筛选:调用
getApplicationListeners()
获取所有符合条件的监听者(过滤、排序)。 - 执行方式:若配置了
Executor
(如线程池),则异步执行;否则同步执行(默认)。 - 调用监听者:通过
invokeListener()
调用监听者的onApplicationEvent()
方法。
- 事件类型解析:通过
3. 监听者筛选(getApplicationListeners)
AbstractApplicationEventMulticaster
的getApplicationListeners()
方法负责筛选符合条件的监听者:
java
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
// 1. 构建缓存键(事件类型+源类型)
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// 2. 从缓存获取(避免重复筛选)
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
// 3. 同步构建缓存(若缓存未命中)
synchronized (this.retrievalMutex) {
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
retriever = new ListenerRetriever(true);
// 4. 筛选监听者(核心逻辑)
Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
- 关键逻辑:
- 缓存机制:使用
ListenerCacheKey
(事件类型+源类型)作为缓存键,避免重复筛选。 - 同步构建:若缓存未命中,同步构建缓存(避免并发问题)。
- 筛选逻辑:调用
retrieveApplicationListeners()
筛选符合条件的监听者。
- 缓存机制:使用
4. 监听者匹配(retrieveApplicationListeners)
retrieveApplicationListeners()
方法遍历所有注册的监听者,通过supportsEvent()
方法判断是否匹配:
java
protected Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
// 1. 获取所有注册的监听者(实例+bean名称)
synchronized (this.retrievalMutex) {
listeners = new LinkedHashSet<>(this.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.applicationListenerBeans);
}
// 2. 处理bean名称注册的监听者(动态初始化)
for (String listenerBeanName : listenerBeans) {
try {
Class<?> listenerType = getBeanFactory().getType(listenerBeanName);
if (listenerType != null && isListenerTypeMatch(listenerType, eventType)) {
ApplicationListener<?> listener = getBeanFactory().getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
allListeners.add(listener);
if (retriever != null) {
retriever.addApplicationListener(listener);
}
}
}
} catch (NoSuchBeanDefinitionException ex) {
// 忽略已销毁的bean
}
}
// 3. 处理实例注册的监听者(静态)
for (ApplicationListener<?> listener : listeners) {
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
allListeners.add(listener);
if (retriever != null) {
retriever.addApplicationListener(listener);
}
}
}
// 4. 排序(按@Order或Ordered接口)
AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null && retriever.isCacheable()) {
retriever.setApplicationListeners(allListeners);
}
return allListeners;
}
- 关键逻辑:
- 动态监听者:通过bean名称注册的监听者,需要从
BeanFactory
获取实例(延迟初始化),并判断是否匹配。 - 静态监听者:通过实例注册的监听者,直接判断是否匹配。
- 匹配逻辑:调用
supportsEvent()
方法判断监听者是否支持当前事件类型和源类型。 - 排序:使用
AnnotationAwareOrderComparator
对监听者排序(@Order
注解或Ordered
接口,值越小优先级越高)。
- 动态监听者:通过bean名称注册的监听者,需要从
5. 监听者匹配规则(supportsEvent)
supportsEvent()
方法根据监听者的类型,判断是否支持当前事件:
java
protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
// 1. SmartApplicationListener:支持事件类型+源类型过滤
if (listener instanceof SmartApplicationListener) {
SmartApplicationListener smartListener = (SmartApplicationListener) listener;
return smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType);
}
// 2. GenericApplicationListener:支持泛型事件类型过滤
else if (listener instanceof GenericApplicationListener) {
return ((GenericApplicationListener) listener).supportsEventType(eventType);
}
// 3. 普通ApplicationListener:根据泛型参数判断(如ApplicationListener<ContextRefreshedEvent>)
else {
Class<?> listenerEventType = resolveListenerEventType(listener);
return (listenerEventType == null || eventType.isAssignableFrom(listenerEventType));
}
}
- 关键逻辑:
SmartApplicationListener
:需同时满足supportsEventType()
(事件类型)和supportsSourceType()
(源类型)。GenericApplicationListener
:支持泛型事件类型(如ApplicationListener<PayloadApplicationEvent<String>>
)。- 普通
ApplicationListener
:根据泛型参数判断(如ApplicationListener<ContextRefreshedEvent>
仅处理ContextRefreshedEvent
及其子类)。
四、@EventListener注解的实现原理
@EventListener
是Spring 4.2引入的注解,用于将普通方法转换为事件监听者。其底层通过EventListenerMethodProcessor
(BeanPostProcessor
)实现。
1. EventListenerMethodProcessor的作用
EventListenerMethodProcessor
实现了BeanPostProcessor
和SmartInitializingSingleton
接口,负责扫描带有@EventListener
的方法,并将其转换为ApplicationListener
。
(1)扫描@EventListener方法(postProcessAfterInitialization)
postProcessAfterInitialization
方法在bean初始化后执行,扫描bean中的@EventListener
方法:
java
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AopInfrastructureBean || bean instanceof EventListenerFactory ||
bean instanceof EventListenerMethodProcessor) {
return bean;
}
// 获取bean的目标类(避免代理类影响)
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
if (!this.nonAnnotatedClasses.contains(targetClass)) {
// 扫描带有@EventListener的方法
Map<Method, EventListener> annotatedMethods = MethodIntrospector.selectMethods(targetClass,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetClass);
} else {
// 处理每个@EventListener方法
for (Map.Entry<Method, EventListener> entry : annotatedMethods.entrySet()) {
Method method = entry.getKey();
EventListener annotation = entry.getValue();
processEventListener(method, annotation, bean, beanName, this.applicationContext);
}
}
}
return bean;
}
- 关键逻辑:
- 跳过特殊bean(如AOP基础设施bean、事件监听工厂等)。
- 扫描目标类中的
@EventListener
方法(使用MethodIntrospector
)。 - 处理每个
@EventListener
方法(调用processEventListener()
)。
(2)转换为ApplicationListener(processEventListener)
processEventListener
方法将@EventListener
方法转换为ApplicationListenerMethodAdapter
(ApplicationListener
的实现类):
java
protected void processEventListener(Method method, EventListener annotation, Object bean, String beanName,
ApplicationContext context) {
// 选择可调用的方法(避免代理方法)
Method methodToUse = AopUtils.selectInvocableMethod(method, bean.getClass());
// 使用EventListenerFactory创建ApplicationListener(默认是DefaultEventListenerFactory)
ApplicationListener<?> applicationListener = this.eventListenerFactory.createApplicationListener(beanName, bean.getClass(), methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
// 初始化适配器(注入ApplicationContext和SpEL表达式 evaluator)
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
// 将ApplicationListener注册到容器
context.addApplicationListener(applicationListener);
}
- 关键逻辑:
- 方法选择:使用
AopUtils.selectInvocableMethod()
选择可调用的方法(避免代理类的方法)。 - 适配器创建:通过
EventListenerFactory
创建ApplicationListenerMethodAdapter
(默认是DefaultEventListenerFactory
)。 - 注册监听者:将
ApplicationListenerMethodAdapter
注册到ApplicationContext
(最终会被添加到多播器)。
- 方法选择:使用
2. ApplicationListenerMethodAdapter的作用
ApplicationListenerMethodAdapter
实现了ApplicationListener
接口,负责将事件转发给@EventListener
方法:
java
@Override
public void onApplicationEvent(ApplicationEvent event) {
processEvent(event);
}
protected void processEvent(ApplicationEvent event) {
// 解析方法参数(如事件对象、源对象、@Payload参数等)
Object[] args = resolveArguments(event);
// 判断是否需要处理(如@EventListener的condition属性)
if (shouldHandle(event, args)) {
// 调用目标方法
invokeMethod(args);
}
}
- 关键逻辑:
- 参数解析:
resolveArguments()
方法解析@EventListener
方法的参数(如event
对象、source
对象、@Payload
注解的参数等)。 - 条件判断:
shouldHandle()
方法判断是否需要处理事件(如@EventListener(condition = "#event.source == 'test'")
中的SpEL表达式)。 - 方法调用:
invokeMethod()
方法调用目标方法(使用反射)。
- 参数解析:
3. @EventListener的条件过滤(condition属性)
@EventListener
的condition
属性支持SpEL表达式,用于过滤事件。例如:
java
@EventListener(condition = "#event.source == 'mySource'")
public void handleEvent(MyEvent event) {
// 处理事件
}
shouldHandle()
方法会评估condition
表达式:
java
protected boolean shouldHandle(ApplicationEvent event, Object[] args) {
if (this.condition == null) {
return true;
}
// 使用SpelExpressionEvaluator评估condition表达式
EvaluationContext evaluationContext = createEvaluationContext(event, args);
return this.evaluator.evaluate(this.condition, evaluationContext, Boolean.class);
}
- 关键逻辑:
- 创建
EvaluationContext
(包含事件对象、方法参数等变量)。 - 使用
SpelExpressionEvaluator
评估condition
表达式,返回true
则处理事件。
- 创建
五、异步事件处理
Spring事件默认是同步执行的(发布者会阻塞直到所有监听者执行完成)。若需异步执行,需配置Executor
(线程池)。
1. 配置异步多播器
通过自定义ApplicationEventMulticaster
bean,设置Executor
:
java
@Configuration
public class AsyncEventConfig {
@Bean(name = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
public ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
// 设置线程池(如ThreadPoolTaskExecutor)
multicaster.setExecutor(taskExecutor());
return multicaster;
}
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(20);
executor.initialize();
return executor;
}
}
2. 异步执行的源码逻辑
SimpleApplicationEventMulticaster
的multicastEvent()
方法中,若Executor
不为null
,则使用线程池异步执行:
java
@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);
}
}
}
- 关键逻辑:
- 若
Executor
不为null
,则将监听者的onApplicationEvent()
方法提交到线程池执行(异步)。 - 否则同步执行(默认)。
- 若
六、内置事件
Spring提供了多个内置事件,用于通知容器的生命周期状态:
事件类名 | 发布时机 |
---|---|
ContextRefreshedEvent | 容器刷新完成(refresh() 方法执行完毕) |
ContextStartedEvent | 容器启动(start() 方法执行完毕) |
ContextStoppedEvent | 容器停止(stop() 方法执行完毕) |
ContextClosedEvent | 容器关闭(close() 方法执行完毕) |
BeanFactoryPostProcessorEvent | BeanFactoryPostProcessor 执行完毕 |
ApplicationReadyEvent | 应用准备就绪(所有bean初始化完成) |
内置事件的发布示例(ContextRefreshedEvent)
AbstractApplicationContext
的finishRefresh()
方法中发布ContextRefreshedEvent
:
java
protected void finishRefresh() {
// 清除资源缓存
clearResourceCaches();
// 初始化生命周期处理器
initLifecycleProcessor();
// 通知生命周期处理器刷新完成
getLifecycleProcessor().onRefresh();
// 发布ContextRefreshedEvent
publishEvent(new ContextRefreshedEvent(this));
// 注册到LiveBeansView(用于监控)
LiveBeansView.registerApplicationContext(this);
}
七、扩展与自定义
Spring事件机制支持灵活扩展,常见的自定义场景包括:
1. 自定义事件
继承ApplicationEvent
或使用PayloadApplicationEvent
(无需继承):
java
// 自定义事件(继承ApplicationEvent)
public class MyEvent extends ApplicationEvent {
private String message;
public MyEvent(Object source, String message) {
super(source);
this.message = message;
}
// getter/setter
}
// 使用PayloadApplicationEvent(无需继承)
applicationContext.publishEvent("myPayload"); // 会被包装为PayloadApplicationEvent<String>
2. 自定义监听者
- 实现
ApplicationListener
接口:java@Component public class MyEventListener implements ApplicationListener<MyEvent> { @Override public void onApplicationEvent(MyEvent event) { System.out.println("处理MyEvent:" + event.getMessage()); } }
- 使用
@EventListener
注解:java@Component public class MyEventListener { @EventListener public void handleMyEvent(MyEvent event) { System.out.println("处理MyEvent:" + event.getMessage()); } }
3. 自定义多播器
实现ApplicationEventMulticaster
接口(或继承AbstractApplicationEventMulticaster
):
java
@Component(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
public class MyEventMulticaster extends AbstractApplicationEventMulticaster {
@Override
public void multicastEvent(ApplicationEvent event) {
// 自定义多播逻辑(如过滤、异步执行等)
for (ApplicationListener<?> listener : getApplicationListeners(event)) {
listener.onApplicationEvent(event);
}
}
@Override
public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
// 自定义多播逻辑
}
}
八、总结
Spring事件通知机制的核心逻辑是:
- 初始化:容器启动时初始化多播器(
SimpleApplicationEventMulticaster
),并注册所有监听者。 - 发布事件:通过
ApplicationContext.publishEvent()
发布事件,底层调用多播器的multicastEvent()
方法。 - 事件传播:多播器筛选符合条件的监听者(根据事件类型、源类型、
@Order
顺序),并同步/异步执行监听者的方法。 - 注解支持:
@EventListener
注解通过EventListenerMethodProcessor
转换为ApplicationListenerMethodAdapter
,实现方法级别的事件监听。
通过这种机制,Spring实现了组件间的解耦(发布者无需知道监听者的存在),并支持同步/异步、事件过滤、顺序控制等灵活特性,是Spring生态中重要的扩展点之一。
关键源码类总结:
- 容器初始化:
AbstractApplicationContext
(refresh()
、initApplicationEventMulticaster()
、registerListeners()
)。 - 多播器:
SimpleApplicationEventMulticaster
(multicastEvent()
)。 - 监听者处理:
EventListenerMethodProcessor
(postProcessAfterInitialization()
)、ApplicationListenerMethodAdapter
(onApplicationEvent()
)。 - 事件类:
ApplicationEvent
、PayloadApplicationEvent
。 - 工具类:
AnnotationAwareOrderComparator
(排序)、ResolvableType
(事件类型解析)。