官方文档之事件:docs.spring.io/spring-fram…
简介
Spring 的事件机制是标准的观察者模式。ApplicationContext 中的事件处理是通过 ApplicationEvent 类和 ApplicationListener 接口提供的:
- 事件(
ApplicationEvent):可以继承ApplicationEvent类表示一个事件 - 事件监听器(
ApplicationListener):可以在方法上使用注解@EventListener或者实现 ApplicationListener 来表示事件监听器 - 事件发布器(
ApplicationEventPublisher):可以在业务方法注入ApplicationEventPublisher 或者 ApplicationContext 来事件发布器
Event handling in the
ApplicationContextis provided through theApplicationEventclass and theApplicationListenerinterface. If a bean that implements theApplicationListenerinterface is deployed into the context, every time anApplicationEventgets published to theApplicationContext, that bean is notified. Essentially, this is the standard Observer design pattern.
注册 ApplicationListener
按程序执行流程,应该先实例化 ApplicationEventMulticaster ,然后将 ApplicationListener 实现类注册进 ApplicationEventMulticaster 实例对象中,最后等待事件的触发并广播事件给符合的 Listener 。这个执行流程都在 AbstractApplicationContext#refresh 方法中。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// 初始化 ApplicationEventMulticaster
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 注册 ApplicationListener
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
初始化 ApplicationEventMulticaster
initApplicationEventMulticaster() 方法完成 ApplicationEventMulticaster 的初始化。如果没有自定义的 ApplicationEventMulticaster 则默认使用 SimpleApplicationEventMulticaster。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 实例化并将实例化的对象注入到 Spring 容器中
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
注册 Listener
通过官方文档可知实现事件监听有2种方式,一种是实现 ApplicationListener 接口,还有一种就是在对象的方法上加 @EventListener 注解也可以完成事件的监听。
注册 ApplicationListener 实现类
registerListeners() 方法完成 ApplicationListener 实现类的注册。
protected void registerListeners() {
// 首先注册硬编码的监听器
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 注册实现了 ApplicationListener 接口的bean,这里只是注册了bean的name。
// 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 (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
注册 @EventListener
@EventListener 是个注解。通过文档得知,将 @EventListener 标记的方法注册为单独的 ApplicationListener 实例就是通过 EventListenerMethodProcessor 类。
EventListenerMethodProcessor 实现了 BeanFactoryPostProcessor,所以执行 BeanFactory 后置处理器时,会调用 postProcessBeanFactory(),将 EventListFactory 接口的实现类 DefaultEventListenerFactory 添加到缓存中。
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
// EventListenerFactory 的默认实现类就是 DefaultEventListenerFactory
Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List<EventListenerFactory> factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
this.eventListenerFactories = factories;
}
EventListenerMethodProcessor 实现了 SmartInitializingSingleton 接口,那肯定要重写 afterSingletonsInstantiated() 方法。SmartInitializingSingleton 接口是在所有的 Bean 实例化完成以后,Spring 回调的方法。
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) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
// ......
try {
// 主要:调用方法处理bean
processBean(beanName, type);
}
catch (Throwable ex) {
throw new BeanInitializationException("Failed to process @EventListener " +
"annotation on bean with name '" + beanName + "'", ex);
}
}
}
}
}
获取所有的 BeanFactory,找到其中标注了 @EventListener 的方法,利用反射和 DefaultEventListenerFactory 为其创建 ApplicationListener,默认实现类ApplicationListenerMethodAdapter ,并添加到ApplicationContext。
private void processBean(final String beanName, final Class<?> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType) && !isSpringContainerClass(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
// 查找带 @EventListener 注解的方法
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
}
catch (Throwable ex) {
// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
}
}
// 如果没有查找到 @EventListener 注解的方法
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetType);
if (logger.isTraceEnabled()) {
logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
}
}
// 否则 ......
else {
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
// EventListenerFactory 是否支持该method的处理
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
// 创建 ApplicationListener 实例,默认实现是 ApplicationListenerMethodAdapter
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
// 注册到 context 中,也就是注册到 ApplicationEventMulticaster 中
context.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
事件的发布/订阅
通过官网文档得知,发布事件是通过调用 ApplicationEventPublisher 的 publishEvent() 方法完成的。而 ApplicationContext 接口实现了 ApplicationEventPublisher接口,所以容器拥有发布事件的功能,其具体实现类为 AbstractApplicationContext。
从 AbstractApplicationContext#publishEvent 入口开始分析。
从代码中可以看出发布事件是调用了getApplicationEventMulticaster().multicastEvent() 方法完成的。顾名思义,就是将事件广播给所有的 listener 接收者。
// AbstractApplicationContext
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 获取 ApplicationEventMulticaster 发布事件
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);
}
}
}
getApplicationEventMulticaster() 方法返回的是一个 ApplicationEventMulticaster 接口实例。由文档得知,实现了此接口的对象可以管理很多实现了 ApplicationListener 的对象并向它们发布事件,其实现类为 SimpleApplicationEventMulticaster。其 multicastEvent() 方法先获取所有支持当前事件的 ApplicationListener 实现类,然后遍历调用 invokeListener() 方法向每个 listener 发布事件。
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);
}
}
}
invokeListener() 方法内部调用了 doInvokeListener() 方法完成事件发布。其实就是调用了 ApplicationListener 的 onApplicationEvent() 方法。
这里注意,通过@EventListener 注解创建的是 ApplicationListenerMethodAdapter类,所以调用的是 ApplicationListenerMethodAdapter#onApplicationEvent 方法。其内部实现为反射调用。
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}