事件机制与Spring ApplicationListener源码详解


事件机制的优势

解耦:用事件机制添加多个业务逻辑操作,不需要与现有的业务逻辑耦合在一起,实现单一职责。在需要的时候还可以很方便的添加或去除一些业务操作,或者将业务操作用其他服务实现异步化。

举例:用户注册成功,系统现有两个后续业务操作:短信通知和邮件通知,这时候就可以用不同监听器去执行,两个操作互不影响,还可以异步执行。

附(劣势):解耦意味着更多业务处理类的加入,维护时需要注意遗漏;异步则需要考虑是否有事务要求,以及执行失败的处理。

1. 事件机制

在这里插入图片描述

1.1 事件

AbstractEvent,内部 source字段表示事件源,一般自定义事件去继承这个抽象父类。

public abstract class AbstractEvent {
    protected Object source;
    
    public AbstractEvent(Object source) {
        this.source = source;
    }
}
1.2 事件监听

EventListener,事件监听的接口,自定义的事件监听器实现这个接口,通过实现 onEvent 方法处理自定义事件。

// 事件监听器,E表示监听器感兴趣的事件类型
public interface EventListener<E extends AbstractEvent>{
    // 处理事件的方法
    void onEvent(E event);
}
1.3 事件发布(广播)

EventMulticaster

  • 事件监听器的管理(注册/移除监听器,将监听器和事件关联起来)
  • 事件广播(将事件广播给所有的监听器,调度感兴趣的监听器处理事件
public interface EventMulticaster {
    // 广播事件给监听器,对该事件感兴趣的监听器会执行处理(遍历监听器的集合等方式,调用相应监听器的onEvent[或者异步调用])
    void multicastEvent(AbstractEvent event);
	// 添加事件监听器(一般放入链表等集合中)
    void addEventListener(EventListener<?listener);
    // 移除事件监听器
    void removeEventListener(EventListener<?listener);
}

2. Spring 实现

Spring事件机制是观察者模式的一种实现,是除了事件源和监听者两个角色之外,还有一个 EventMultiCaster 的角色负责把事件转发(广播)给监听者。

2.1 相应 API

事件

ApplicationEvent

public abstract class ApplicationEvent extends EventObject {
	/** System time when the event happened. */
	private final long timestamp;

	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}
}

事件监听

Spring 创建事件监听器并注册到广播器上有两种方式,实现 ApplicationListener 、使用 @EventListener 注解。

spring4.2 版本之后,提供 @EventListener 注解用于 public 方式,自定义事件作为形参可以直接注册为监听器。

注:两种方式的 Listener 都需要用 Spring 管理 Bean 才行。

注2:如果被 @EventListener 标注的方法返回一个 Event,那么 Spring 将继续发布此 event。

  • 事件监听1 ApplicationListener
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	/** Handle an application event. */
	void onApplicationEvent(E event);
}
  • 事件监听2 @EventListener
@Component
public class AnnotationDrivenContextStartedListener {
 
    /** 注册的事件就是 HelloEvent,onEvent的处理是 messageListener 方法 */
    @EventListener(HelloEvent.class)
    public void messageListener(HelloEvent helloEvent){
        System.out.println("AnnotationDrivenContextStartedListener:"+helloEvent.message);
    }
}

事件发布

Spring 发布事件有两种方式,方式一是实现 ApplicationContextAware或实现 ApplicationEventPublisherAware,方式二是使用 @EventListener。

注:本质上是一致的,ApplicationContextAware 获取到 ApplicationContext,ApplicationContext 继承了 ApplicationEventPublisher;ApplicationEventPublisherAware 直接获取到 ApplicationEventPublisher。

  • 事件发布1 ApplicationContextAware
public interface ApplicationContextAware extends Aware {
	/** 获取一个 ApplicationContext,用这个对象来执行发布 */
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
  • 事件发布2 ApplicationEventPublisherAware
public interface ApplicationEventPublisherAware extends Aware {
	/** 获取一个 ApplicationEventPublisher,用这个对象来执行发布{这个对象是否也是ApplicationContext?待验证} */
	void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);
}

ApplicationContextApplicationEventPublisher

// 继承了 ApplicationEventPublisher
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    // ...
}

public interface ApplicationEventPublisher {
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}
	// 发布/广播事件(AbstractApplicationContext 会执行 EventMulticaster.multicastEvent(event))
	void publishEvent(Object event);
}
2.2 继承 ApplicationListener 注册实现分析

org.springframework.context.support.AbstractApplicationContext#addApplicationListener

执行调用分析:

refresh -> finishBeanFactoryInitialization -> ... -> getBean -> ... -> doCreateBean -> initializeBean -> ... -> postProcessAfterInitalization -> addApplicationListener

注1:

finishBeanFactoryInitialization 这一步并不是 addApplicationListener 的唯一入口,invokeBeanFactoryPostProcessors、registerBeanPostProcessors、onRefresh等方法,甚至 SpringApplication.prepareContext(在refresh前) 也可能会执行添加;

注2:

继承于 ApplicationListener 的监听器注册原理:bean 执行 initializeBean 时,Spring 的后置处理器 ApplicationListenerDetector 将对这个 Bean 执行 addApplicationListener。

附1:

ApplicationListenerDetector 属于 Spring 提供的内置后置处理器,prepareBeanFactory时{refresh的一个步骤}将 ApplicationListenerDetector 添加到 beanPostProcessors 后置处理器队列中{org.springframework.beans.factory.support.AbstractBeanFactory#beanPostProcessors};

ApplicationListenerDetector 的顶层接口是 BeanPostProcessor,BeanPostProcessor主要提供了两个抽象方法:postProcessBeforeInitialization、postProcessAfterInitialization,这两个方法分别在 initializeBean 调用 invokeInitMethods{org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods}前后调用,以实现对 Bean 初始化时的一些特殊处理。

附2:

结合附1,ApplicationContextAware 对应的 BeanProcessor 是 ApplicationContextAwareProcessor,包括其他一些也是需要获取容器上下文的接口,如 ApplicationEventPublisherAware、EnvironmentAware等。具体可以查看 org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization。

ApplicationContextAwareProcessor 也是在 prepareBeanFactory 时加入的后置处理器队列。

继承ApplicationListener注册监听器时序图

在这里插入图片描述

initializeBean
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);		// 一些aware接口的处理,如BeanNameAware
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);	// 初始化前处理(后置处理器)
    }

    try {
        invokeInitMethods(beanName, wrappedBean, mbd);			// 初始化init
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);	// 初始化后处理(后置处理器)
    }

    return wrappedBean;
}
applyBeanPostProcessorsBeforeInitialization
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
postProcessBeforeInitialization
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
postProcessAfterInitialization
// org.springframework.context.support.ApplicationListenerDetector#postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
   if (bean instanceof ApplicationListener) {
      // potentially not detected as a listener by getBeanNamesForType retrieval
      Boolean flag = this.singletonNames.get(beanName);
      if (Boolean.TRUE.equals(flag)) {
         // singleton bean (top-level or inner): register on the fly
         this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
      }
      else if (Boolean.FALSE.equals(flag)) {
         if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
            // inner bean with other scope - can't reliably process events
            logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                  "but is not reachable for event multicasting by its containing ApplicationContext " +
                  "because it does not have singleton scope. Only top-level listener beans are allowed " +
                  "to be of non-singleton scope.");
         }
         this.singletonNames.remove(beanName);
      }
   }
   return bean;
}
addApplicationListener
// org.springframework.context.support.AbstractApplicationContext#addApplicationListener
public void addApplicationListener(ApplicationListener<?> listener) {
   Assert.notNull(listener, "ApplicationListener must not be null");
   if (this.applicationEventMulticaster != null) {
      this.applicationEventMulticaster.addApplicationListener(listener);	// 注册到广播器中
   }
   this.applicationListeners.add(listener);
}
2.3 事件广播、处理源码分析
  • 事件发布 applicationContext.publishEvent(applicationEvent)
/** org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType) */
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    // do sth...
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    } else {
        // 广播器广播给事件监听器
        this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
    }
    // if have parent, continue to publish...
}
/** org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType) */
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
    Executor executor = this.getTaskExecutor();			//事件处理的线程池(没有设置异步处理的线程池则由发布的线程处理)
    Iterator var5 = this.getApplicationListeners(event, type).iterator();	//根据事件类型寻找已经注册的感兴趣的监听器

    while(var5.hasNext()) {	
        ApplicationListener<?> listener = (ApplicationListener)var5.next();
        if (executor != null) {
            executor.execute(() -> {		//交由监听器处理事件(异步)
                this.invokeListener(listener, event);
            });
        } else {
            this.invokeListener(listener, event);
        }
    }

}
  • 监听器处理
/** org.springframework.context.event.SimpleApplicationEventMulticaster#doInvokeListener */
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    try {
        listener.onApplicationEvent(event);		//监听器继承ApplicationListener重写的处理方法
    } catch (ClassCastException var6) {
        String msg = var6.getMessage();
        if (msg != null && !this.matchesClassCastMessage(msg, event.getClass())) {
            throw var6;
        }

        Log logger = LogFactory.getLog(this.getClass());
        if (logger.isTraceEnabled()) {
            logger.trace("Non-matching event type for listener: " + listener, var6);
        }
    }

}
2.4 @EventListener 注册实现分析

@EventListener 加在 Spring 管理的 bean 的方法上,可以将该方法当成事件处理,其实现由 EventListenerMethodProcessor 支持。

(1)EventListenerMethodProcessor 注入

/** 
路径扫描时调用,AnnotationConfigUtils 将 Spring 的一些底层处理类的 BeanDefinition 加入容器中
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
*/
	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
        // ...
        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));
		}
        // ...
    }

(2)EventListenerMethodProcessor 调用

调用链路:AbstractApplicationContext.refresh() -> finishBeanFactoryInitialization(…) -> ConfigurableListableBeanFactory.preInstantiateSingletons()

	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
        // ...
        // Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);	
            // EventListenerMethodProcessor实现了SmartInitializingSingleton 接口
			if (singletonInstance instanceof SmartInitializingSingleton) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
    }

(3)EventListenerMethodProcessor 实现

public class EventListenerMethodProcessor
		implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {
    // afterSingletonsInstantiated() 调用 processBean
	private void processBean(final String beanName, final Class<?> targetType) {
		if (!this.nonAnnotatedClasses.contains(targetType) &&
				AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
				!isSpringContainerClass(targetType)) {

			Map<Method, EventListener> annotatedMethods = null;
			try {
                // 查找类上声明了 @EventListener 的方法
				annotatedMethods = MethodIntrospector.selectMethods(targetType,
						(MethodIntrospector.MetadataLookup<EventListener>) method ->
								AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
			}
			// ...
			else {
				// ...
				for (Method method : annotatedMethods.keySet()) {
					for (EventListenerFactory factory : factories) {
						if (factory.supportsMethod(method)) {
							Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
                            // 适配器模式做适配(注意是适配器模式,这里并没有做成代理的方式)
							ApplicationListener<?> applicationListener =
									factory.createApplicationListener(beanName, targetType, methodToUse);
							if (applicationListener instanceof ApplicationListenerMethodAdapter) {
								((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
							}
                            // 注册监听器
							context.addApplicationListener(applicationListener);
							break;
						}
					}
				}
				//... 
			}
		}
	}
}

注:监听器排序可以看 AnnotationAwareOrderComparator

2.5 异步处理
方式一:设置taskExecutor

SimpleApplicationEventMulticaster 没有初始化 taskExecutor,可以通过自定义 bean 和传入线程池作为属性参数的方式,创建一个带线程池的ApplicationEventMulticaster。

/** 类似于以下定义 */
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
	ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    // executor properties...
    return taskExecutor;
}

@Bean
public SimpleApplicationEventMulticaster applicationEventMulticaster(ConfigurableListableBeanFactory beanFactory,
ThreadPoolTaskExecutor taskExecutor) {
    SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster(beanFactory);
    multicaster.setTaskExecutor(taskExecutor);
    return multicaster;
}
方式二:@Async

由 AsyncAnnotationBeanPostProcessor 进行后置处理,利用代理机制异步线程完成特定方法的异步任务处理

(1)处理器注入

// Spring提供的bean,将 AsyncAnnotationBeanPostProcessor 注入容器中
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {

	@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
		Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
		AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();		// 异步后置处理器
		bpp.configure(this.executor, this.exceptionHandler);	// 线程和异常处理由AbstractAsyncConfiguration注入
		Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
		if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
			bpp.setAsyncAnnotationType(customAsyncAnnotation);
		}
		bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
		bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
		return bpp;
	}

}

(2)处理器注册

// 入口是 org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors
final class PostProcessorRegistrationDelegate {
    // 根据类型从容器中取出处理器,经过排序等一些处理后,添加进处理器队列
	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
         // ...
         for (String ppName : postProcessorNames) {
            // ...
         }
       	 // ...
    }
}

(3)处理器的处理逻辑

/** AsyncAnnotationBeanPostProcessor的父类 */
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {
    @Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		// 没有通知,或者是AOP的基础设施类,那么不进行代理
        if (this.advisor == null || bean instanceof AopInfrastructureBean) {
			// Ignore AOP infrastructure such as scoped proxies.
			return bean;
		}
		// 对已经被代理的类,不再生成代理,只是将通知添加到代理类的逻辑中
		if (bean instanceof Advised) {
			Advised advised = (Advised) bean;
			if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
				// Add our local Advisor to the existing proxy's Advisor chain...
				if (this.beforeExistingAdvisors) {
					advised.addAdvisor(0, this.advisor);
				}
				else {
					advised.addAdvisor(this.advisor);
				}
				return bean;
			}
		}
		// 判断需要对哪些Bean进行来代理,通过创建代理去处理
		if (isEligible(bean, beanName)) {
			ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
			if (!proxyFactory.isProxyTargetClass()) {
				evaluateProxyInterfaces(bean.getClass(), proxyFactory);
			}
			proxyFactory.addAdvisor(this.advisor);
			customizeProxyFactory(proxyFactory);
			return proxyFactory.getProxy(getProxyClassLoader());
		}

		// No proxy needed.
		return bean;
	}
}

// 异步处理,advisor调用builderAdvice时,创建一个AnnotationAsyncExecutionInterceptor跟advisor绑定,线程提交任务在AnnotationAsyncExecutionInterceptor的父类中
(SpringBoot开启异步)

(1)SpringBoot启用@EnableAsync

@SpringBootApplication(exclude = xxx.class)
@EnableAsync(proxyTargetClass = true)		//启用异步,true使用cglib(默认false使用JDK)
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

(2)@EnableAsync开启异步实现

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)		// 了解@Import的3种加载方式
public @interface EnableAsync {
    //...
}

(3)AsyncConfigurationSelector选择异步方式

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
    // ...
	@Override
	@Nullable
	public String[] selectImports(AdviceMode adviceMode) {		//父类的selectImports会将ProxyAsyncConfiguration放入IOC加载的队列
		switch (adviceMode) {
			case PROXY:			// @EnableAsync 配置默认值,默认使用SpringAOP代理
				return new String[] {ProxyAsyncConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
			default:
				return null;
		}
	}
}

参考:Sping事件机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值