Spring 事件
abstract ApplicationEvent extends EventObject
abstract ApplicationContextEvent extends ApplicationEvent
ApplicationContext 作为数据源,方便后续的交互
具体实现
ContextClosedEvent
ContextRefreshedEvent
ContextStartedEvent
ContextStoppedEvent
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
代码示例
context.addApplicationListener(new ApplicationListener<ApplicationEvent>() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
println("ApplicationListener - 接收到 Spring 事件:" + event);
}
});
//或者,将ApplicationListener注册为Bean,同样也能够接收到事件
context.register(new MyApplicationListener())
ApplicationContext#refresh() , 会将所有的ApplicationListener添加到一个集合中
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
所以通过addApplicationListener 和 将ApplicationListener注册成为Bean都可以接收到事件。
@EventListener
public @interface EventListener {
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String condition() default "";
}
代码示例
@EventListener
public void onApplicationEvent(ApplicationEvent event) {
println("@EventListener - 接收到 Spring 事件:"+event);
}
@EventListener ——> ApplicationListener . 两个事件先后触发(多个,refresh、start、close等)
@Async 可以使事件异步触发。(标明 @EnableAsync)
@Order 配合控制事件优先级,数值越小,优先级越高
Spring 事件发布器
ApplicationEventPublisher
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
实现 ApplicationEventPublisherAware ,重写 setApplicationEventPublisher ,通过注入拿到 ApplicationEventPublisher 对象
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
applicationEventPublisher.publishEvent(new ApplicationEvent("Hello,World") {
});//默认的重载方法,指定类型为 ApplicationEvent
// 发送 PayloadApplicationEvent
applicationEventPublisher.publishEvent("Hello,World");//不指定类型,Spring 默认实现为PayloadApplicationEvent
applicationEventPublisher.publishEvent(new MyPayloadApplicationEvent(this, "Hello,World"));
}
注:ApplicationContext 可以指定 parent , 在自己发送完事件的时候,还会去询问是否有parent ,如果有会通过parent再次发送当前的Event,这里需要小心的是,虽然是通过parent来发送,但是,事件还是当前Context的,所以,还是会有当前的Context来接收,而不是parent。所以会导致一个事件两次处理,就需要在开发中自己过滤掉已经处理过的事件,避免重复处理。
AbstarctApplicationContext#publishEvent
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
ApplicationEventMulticaster
public interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> listener);
void addApplicationListenerBean(String listenerBeanName);
void removeApplicationListener(ApplicationListener<?> listener);
void removeApplicationListenerBean(String listenerBeanName);
void removeAllListeners();
/**
* Multicast the given application event to appropriate listeners.
* <p>Consider using {@link #multicastEvent(ApplicationEvent, ResolvableType)}
* if possible as it provides better support for generics-based events.
* @param event the event to multicast
*/
void multicastEvent(ApplicationEvent event);//广播给定的事件到合适的listeners
/**
* Multicast the given application event to appropriate listeners.
* <p>If the {@code eventType} is {@code null}, a default type is built
* based on the {@code event} instance.
* @param event the event to multicast
* @param eventType the type of event (can be {@code null})
* @since 4.2
*/
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);//eventType 匹配事件
}
这个接口是Spring 事件的底层实现。在 AbstractApplicationContext这个类里面有这样的方法 addApplicationListener 内部实现是这样的:
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
Assert.notNull(listener, "ApplicationListener must not be null");
if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.addApplicationListener(listener);
}
else {
this.applicationListeners.add(listener); //后续还是通过applicationEventMulticaster处理的
}
}
可以看出来,内部是委派给了 ApplicationEventMulticaster 去处理的。
earlyApplicationEvents
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
....
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
....
}
这里需要注意的是在 ApplicationMulticaster还没有初始化的时候,定义了一个集合用来存储在初始化之前的事件。这种情况很少见,但是会有这样的情况出现。比如说,一个 Configuration Class ,同时实现了 BeanPostProcessor 和 ApplicationEventPublisherAware 就会出现事件早于ApplicationMulticaster初始化的发生。
#AbstractApplicationContext
registerBeanPostProcessors()
#PostProcessorRegistrationDelegate
registerBeanPostProcessors()
#AbstractBeanFactory
doGetBean()
....
#AbstractAutowireCapableFactory
applyBeanPostProcessorsBeforeInitialization()
#ApplicationContextAwareProcessor
postProcessBeforeInitialization()
//最后会回调 实现了 ApplicationEventPublisherAware
private void invokeAwareInterfaces(Object bean) {
....
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
....
}
这整个的过程起始点在 AbstractApplicationContext#refresh() ,在这个方法里会先后调用 registerBeanPostProcessors() 和 initApplicationEventMulticaster() ,所以就会出现上述所说的有些事件会先于 ApplicationMulticaster的初始化。
@EventListener
@EventListener
public void onEvent(MySpringEvent event) {
System.out.printf("[线程 : %s] onEvent方法监听到事件 : %s\n", Thread.currentThread().getName(), event);
}
context.publishEvent(new MySpringEvent("Hello,World"));
以上代码便是注解的方式实现事件的监听。这个注解的处理主要是由 EventListenerMethodProcessor 这个 BeanFactoryPostProcessor 来负责的。
EventListenerMethodProcessor#processBean
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); //拿到@EventListener注解标注的 onEvent方法
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
//factory 指的是 EventListenerFactory 默认实现类 DefaultEventListenerFactory
//factory.createApplicationListener 得到的是 ApplicationListenerMethodAdapter
//ApplicationListenerMethodAdapter 实现了 ApplicationListener
//ApplicationListenerMethodAdapter内部会去处理 优先级、类的类型(Resolvable)、Reactive等
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
context.addApplicationListener(applicationListener);
break;
}
}
}
DefaultEventListenerFactory
@Override
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
return new ApplicationListenerMethodAdapter(beanName, type, method);
}
这样就可以清楚的知道 @EventListener 内部的实现过程。
addApplicationListener
我们知道一个Event事件可以有多个Listener;一个Listener可以有多个Event,这里的Event主要是有继承关系,也就是说Listener可以监听一个父Event以及它所有的子Event。
-
一个Listener监听多个Event
SimpleApplicationEventMulticaster#multicastEvent @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)) {//找到对应的Listener if (executor != null) { //处理异步事件 executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); //处理同步事件 } } } //接着会调用这个方法 AbstractApplicationEventMulticaster#retrieveApplicationListeners private Collection<ApplicationListener<?>> retrieveApplicationListeners( ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) { .... // Add programmatically registered listeners, including ones coming // from ApplicationListenerDetector (singleton beans and inner beans). for (ApplicationListener<?> listener : listeners) { if (supportsEvent(listener, eventType, sourceType)) { //会去判断Listener是否支持Event的监听 if (retriever != null) { retriever.applicationListeners.add(listener); } allListeners.add(listener); } } .... } //接着会调用 GenericApplicationListenerAdapter#supportsEventType @Override @SuppressWarnings("unchecked") public boolean supportsEventType(ResolvableType eventType) { .... else { return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType)); //这里会判断Listener<Event> 类的泛型类型是否是当前 multicast 的Event类型或者是否是其父类型 } } -
一个Event多个Listener
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware { //一个ListenerCacheKey 对应一个 ListenerRetriever final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64); .... } // EventType 、SourceType 构建出来的对象,相当于一个Event对应一个ListenerCacheKey private static final class ListenerCacheKey implements Comparable<ListenerCacheKey> { private final ResolvableType eventType; @Nullable private final Class<?> sourceType; .... } private class ListenerRetriever { //包含了多个Listener public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>(); .... }