1 自定义ApplicationEventListener
自定义ApplicationEventListener的两种方式:
- 实现ApplicationListener接口
- 使用@EventListener注解
package com.woods.listener;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.woods.listener")
public class App {
}
package com.woods.listener;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext configApplicationContext =
new AnnotationConfigApplicationContext(App.class);
// 发布一个自定义事件
configApplicationContext.publishEvent(new ApplicationEvent(new String("This is a custom listener")) {
@Override
public String toString() {
return super.toString();
}
});
configApplicationContext.close();
}
}
package com.woods.listener;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* 通过实现ApplicationListener接口创建自定义的ApplicationEventListener
*/
@Component
public class MyApplicationEventListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("onApplicationEvent收到事件 " + event);
}
/**
* 如果@EventListener标记的方法的返回值不是void,返回的对象将被包装成一个PayloadApplicationEvent再次被发送。
* */
// @EventListener
// public int doSomething1(ApplicationEvent event) {
// System.out.println("EventListener1收到事件 " + event);
// return 1;
// }
}
package com.woods.listener;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* 通过@EventListener注解创建自定义的ApplicationEventListener
*/
@Component
public class MyApplicationEventListener2 {
@EventListener
public void doSomething2(ApplicationEvent event) {
System.out.println("EventListener收到事件 " + event);
}
}
上面代码的运行结果为:
EventListener收到事件 org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@d716361, started on Tue Jul 28 20:26:01 CST 2020]
onApplicationEvent收到事件 org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@d716361, started on Tue Jul 28 20:26:01 CST 2020]
EventListener收到事件 com.woods.listener.Main$1[source=This is a custom listener]
onApplicationEvent收到事件 com.woods.listener.Main$1[source=This is a custom listener]
EventListener收到事件 org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@d716361, started on Tue Jul 28 20:26:01 CST 2020]
onApplicationEvent收到事件 org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@d716361, started on Tue Jul 28 20:26:01 CST 2020]
Spring的ApplicationContext的事件处理机制是对Observer设计模式的一种实现。
SpringFramework官方文档的1.15.2节对SpringFramework的事件机制进行了讲解,主要涉及到的对象包括
- ApplicationEvent,代表事件。Spring提供的标准事件包括ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent、RequestHandledEvent、ServletRequestHandledEvent。用户可以通过继承ApplicationEvent自定义事件。
- ApplicationListener,代表事件监听器。可以通过实现ApplicationListener接口或通过@EventListener注解(Spring4.2开始支持)标注方法的方式创建自定义的事件监听器。ApplicationListener#onApplicationEvent用于处理接收到的事件,默认情况下在调用者线程中处理。如果在@EventListener注解上加上@Async,则会在一个单独的线程中进行事件的处理。此外,还可以在@EventListener注解上加上@Order注解确定ApplicationListener的处理顺序。
- ApplicationEventPublisher,事件发布器。ApplicationEventPublisher#publishEvent方法可以发布事件。可以通过实现ApplicationEventPublisherAware接口获得ApplicationEventPublisher。
- ApplicationEventMulticaster,事件广播器。ApplicationEventMulticaster用来管理ApplicationListener,例如addApplicationListener、removeApplicationListener。此外,可以向listener广播事件,即ApplicationEventMulticaster#multicastEvent(ApplicationEvent)
2 源码分析
2.1 对ApplicationListener子类和@EventListener的处理流程
-
1 在AnnotationConfigApplicationContext的构造方法中,向BeanFactory注册了两个BeanDefinition,分别是EventListenerMethodProcessor和DefaultEventListenerFactory。
EventListenerMethodProcessor实现了BeanFactoryPostProcessor接口和SmartInitializingSingleton接口,EventListenerMethodProcessor的postProcessAfterInitialization方法会将实现了ApplicationListener接口的类添加到ApplicationEventMulticaster,而EventListenerMethodProcessor的afterSingletonsInstantiated方法则会让DefaultEventListenerFactory为标注了@EventListener注解的方法生成ApplicationListenerMethodAdapter,然后添加到ApplicationEventMulticaster。
DefaultEventListenerFactory是为@EventListener标注的方法生成ApplicationListener的工厂。 -
2 在AbstractApplicationContext的refresh方法中,首先执行prepareBeanFactory方法,该方法向BeanFactory添加了ApplicationListenerDetector这个Bean。ApplicationListenerDetector实现了BeanPostProcessor接口,在Bean实例化之后会调用BeanPostProcessor的postProcessAfterInitialization方法。ApplicationListenerDetector的postProcessAfterInitialization会把实现了ApplicationListener接口的Bean,也就是用户自定义的ApplicationListener注册到ApplicationEventMulticaster上。
-
3 接着执行refresh中的invokeBeanFactoryPostProcessor方法。由于在第1步中注册的EventListenerMethodProcessor实现了BeanFactoryPostProcessor接口,因此在这里会创建EventListenerMethodProcessor对应的Bean,并调用EventListenerMethodProcessor的postProcessBeanFactory方法,该方法会根据第1步中添加到BeanFactory中的EventListenerMethodProcessor对应的BeanDefinition,创建出EventListenerMethodProcessor对应的Bean。在EventListenerMethodProcessor的afterSingletonsInstantiated方法中,会先获取所有的DefaultEventListenerFactory,EventListenerMethodProcessor会为标注了@EventListener的方法生成ApplicationListenerMethodAdapter,然后EventListenerMethodProcessor会把生成的ApplicationListenerMethodAdapter并绑定到ApplicationEventMulticaster上。
经过上面3步,EventListenerMethodProcessor、DefaultEventListenerFactory和ApplicationListenerDetector都已经是Bean了。 -
4 initApplicationEventMulticaster方法中创建了ApplicationEventMulticaster的实现类,即SimpleApplicationEventMulticaster,所有的ApplicationListener都会注册到SimpleApplicationEventMulticaster中。在SimpleApplicationEventMulticaster发布事件时,会把事件传递给每个ApplicationListener,每个ApplicationListener调用onApplicationEvent方法处理收到的事件。
-
5 registerListeners方法将所有ApplicationListener对应的BeanName关联到了ApplicationEventMulticaster上。
-
6 finishBeanFactoryInitialization方法完成单实例Bean的创建。创建完成后,会执行到BeanPostProcessor的postProcessAfterInitialization方法。ApplicationListenerDetector实现了BeanPostProcessor接口,它的postProcessAfterInitialization会把实现了ApplicationListener接口的Bean,也就是用户自定义的ApplicationListener注册到ApplicationEventMulticaster上。
-
7 在finishBeanFactoryInitialization方法方法的最后,会执行smartSingleton.afterSingletonsInstantiated()方法。ApplicationListenerDetector实现了SmartInitializingSingleton接口,在EventListenerMethodProcessor的afterSingletonsInstantiated方法中,会先获取所有的DefaultEventListenerFactory,EventListenerMethodProcessor会为标注了@EventListener的方法生成ApplicationListenerMethodAdapter,然后EventListenerMethodProcessor会把生成的ApplicationListenerMethodAdapter并绑定到ApplicationEventMulticaster上。
至此,实现了ApplicationListener接口的以及标注了@EventListener注解的方法都变成了ApplicationListener并关联到了ApplicationEventMulticaster中。
2.2 几个重要的类
-
ApplicationListenerDetector处理实现了ApplicationListener接口的类。具体来讲,ApplicationListenerDetector实现了BeanPostProcessor接口,
在ApplicationListener子类被创建成Bean之后,ApplicationListenerDetector的postProcessAfterInitialization方法会将ApplicationListener子类添加到applicationEventMulticaster中,这样就把用户自定义的ApplicationListener和ApplicationEventMulticaster联系在了一起。 -
EventListenerMethodProcessor和DefaultEventListenerFactory处理@EventListener标注的方法,为这样的方法生成ApplicationListenerMethodAdapter(ApplicationListenerMethodAdapter实现了ApplicationListener接口)并添加到applicationEventMulticaster中,这样就把@EventListener标注的方法生成的ApplicationListener和ApplicationEventMulticaster联系在了一起。
2.3 源码分析
与事件处理相关的代码分散在AnnotationConfigApplicationContext初始化过程的各个阶段,主要包括:
- AnnotationConfigApplicationContext构造方法,this.reader = new AnnotatedBeanDefinitionReader(this)。
这里向BeanFactory中添加EventListenerMethodProcessor和DefaultEventListenerFactory这两个BeanDefinition。EventListenerMethodProcessor和DefaultEventListenerFactory与事件处理相关。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
......省略部分无关代码
// EventListenerMethodProcessor是BeanFactoryPostProcessor
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
// DefaultEventListenerFactory,为@EventListener标注的方法生成ApplicationListenerMethodAdapter
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
EventListenerMethodProcessor的postProcessBeanFactory方法如下。该方法将DefaultEventListenerFactory生成Bean,存储到eventListenerFactories中。
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List<EventListenerFactory> factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
this.eventListenerFactories = factories;
}
EventListenerMethodProcessor的afterSingletonsInstantiated方法如下。该方法的主要逻辑是调用上面postProcessBeanFactory产生的eventListenerFactories中的每个EventListenerFactory的createApplicationListener方法,为标注了@EventListener注解的方法生成ApplicationListenerMethodAdapter,然后将该ApplicationListener与ApplicationEventMulticaster关联起来。
@Override
public void afterSingletonsInstantiated() {
ConfigurableListableBeanFactory beanFactory = this.beanFactory;
Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
......省略部分代码
try {
processBean(beanName, type);
}
catch (Throwable ex) {
throw new BeanInitializationException("Failed to process @EventListener " +
"annotation on bean with name '" + beanName + "'", ex);
}
}
}
}
}
private void processBean(final String beanName, final Class<?> targetType) {
......
// 取出postProcessBeanFactory生成的DefaultEventListenerFactory Bean实例
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
// 调用DefaultEventListenerFactory的createApplicationListener方法,为标注了@EventListener注解的方法生成ApplicationListenerMethodAdapter
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
// 添加到ApplicationContext中并添加到ApplicationEventMulticaster中
context.addApplicationListener(applicationListener);
break;
}
}
}
.......
}
-
AbstractApplicationContext的refresh方法。
- initApplicationEventMulticaster。默认创建一个SimpleApplicationEventMulticaster。
- registerListeners()。获取ApplicationListener的BeanName,添加到SimpleApplicationEventMulticaster中。
- finishBeanFactoryInitialization(beanFactory)。创建MyApplicationEventListener2这个Bean时,在initializeBean方法中,会调用ApplicationListenerDetector的postProcessAfterInitialization方法,将MyApplicationEventListener2这个Bean关联到SimpleApplicationEventMulticaster上。
对实现了ApplicationListener接口的处理,这里是上面例子中的MyApplicationEventListener2
对标注了@EventListener注解的方法的处理,这里是MyApplicationEventListener2的doSomething2方法。
2.4 事件的发送与接收
终于到了发送事件这个轻松愉快的环节,我们看下ContextRefreshedEvent事件是怎么发送以及如何被我们自定义的ApplicationListener处理的。
// 1 Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// 2 获取ApplicationEventMulticaster,调用multicastEvent方法
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
// 3 拿到所有的ApplicationListener,调用每个的onApplicationEvent方法处理事件
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);
}
}
}
调用栈如下