Spring事件监听机制源码解析
Spring事件监听器使用
1.Spring事件监听体系包括三个组件:事件、事件监听器,事件广播器。
事件:定义事件类型和事件源,需要继承ApplicationEvent。
package com.ybe.eventLisitener;
import org.springframework.context.ApplicationEvent;
public class OrderEvent extends ApplicationEvent {
private String name;
public OrderEvent(Object source,String name) {
super(source);
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
事件监听器:用来监听某一类的事件,并且执行具体业务逻辑,需要实现ApplicationListener 接口或者需要用@ListenerEvent(T)注解。好比观察者模式中的观察者。
package com.ybe.eventLisitener;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class OrderEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(OrderEvent event) {
if(event.getName().equals("下订单")){
System.out.println("下单已完成...");
}
}
}
package com.ybe.eventLisitener;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class OrderEventListenerByAnnotation{@EventListener(OrderEvent.class)
public void onApplicationEvent(OrderEvent event) {
if(event.getName().equals("下订单")){
System.out.println("下单已完成...");
}
}
}
事件多播器:负责广播通知所有监听器,所有的事件监听器都注册在了事件多播器中。好比观察者模式中的被观察者。Spring容器默认生成的是同步事件多播器。可以自定义事件多播器,定义为异步方式。
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.stereotype.Component;
import java.util.Scanner;
@Configuration
@ComponentScan(value = "https://www.it610.com/article/com.ybe")
public class Config {
@Bean
public ApplicationEventMulticaster applicationEventMulticaster(){
SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
return eventMulticaster;
}
}
Spring事件源码分析 1.创建多播器 创建 AnnotationConfigApplicationContext 的过程中,会执行refresh()中的initApplicationEventMulticaster()方法。该方法先获取bean工厂,然后判断工厂是否包含了beanName 为 applicationEventMulticaster的bean。如果包含了,则获取该bean,赋值给applicationEventMulticaster 属性。如果没有,则创建一个 SimpleApplicationEventMulticaster 对象,并且赋值给 applicationEventMulticaster 。实现了源码如下:
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
// 获取当前bean工厂,一般是DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 判断容器中是否存在bdName为applicationEventMulticaster的bd,
//也就是说自定义的事件监听多路广播器,必须实现ApplicationEventMulticaster接口
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
// 如果有,则从bean工厂得到这个bean对象
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 如果没有,则默认采用SimpleApplicationEventMulticaster
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() + "]");
}
}
}
2.注册监听器 监听器的注册有两种,通过实现 ApplicationListener接口或者添加@EventListener注解。
一.通过接口方式注册。实现接口 ApplicationListener 。 注册的逻辑实现在refresh()中的registerListeners()方法里面。第一步,先获取当前ApplicationContext中已经添加的 applicationListeners(SpringMVC源码中有用到),遍历添加到多播器中。第二步,获取实现了ApplicationListener接口的listenerBeanNames集合,添加至多播器中。第三步,判断是否有早期事件,如果有则发起广播。
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!
// 从容器中获取所有实现了ApplicationListener接口的bd的bdName
// 放入ApplicationListenerBeans集合中
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 earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
思考一下,上面的代码中第二步为啥添加的是listenerBeanName?
如果监听器是懒加载的话(即有@Lazy 注解)。那么在这个时候创建监听器显然是不对的,这个时候不能创建监听器。所以添加监听器到多播器的具体逻辑放在初始化具体的监听器之后。通过 BeanPostProcessor 的接口实现。具体的实现类是 ApplicationListenerDetector 。这个类是在 refreah()中prepareBeanFactory()方法中添加的。代码如下:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
// 添加 监听器后置处理器,在初始化具体的实现了 ApplicationListener 接口的Bean之后,进行调用。调用的是
// postProcessAfterInitialization()方法。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
二、通过注解的方式注册。@EventListener(T)。 在创建 AnnotationConfigApplicationContext 的构造方法中,会执行org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 方法。这个方法中会添加两个 beanDefs, 代码如下:
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));
}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));
}
EventListenerMethodProcessor:事件监听器的BeanFactory后置处理器,在前期会创建 DefaultEventListenerFactory ,后期在创建好Bean之后,根据 EventListener 属性,调用DefaultEventListenerFactory创建具体的 ApplicationListenerMethodAdapter 。
DefaultEventListenerFactory:监听器的创建工厂,用来创建 ApplicationListenerMethodAdapter 。
EventListenerMethodProcessor 的类继承图如下:

文章图片
在refreash的invokeBeanFactoryPostProcessors()中会调用 org.springframework.context.event.EventListenerMethodProcessor#postProcessBeanFactory方法,获取EventListenerFactory 类型的 Bean。代码如下:
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
// 获取或创建 EventListenerFactory 类型的 Bean
Map beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
this.eventListenerFactories = factories;
}
在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,创建完所有的单例Bean 之后,会遍历所有Bean是否实现了 SmartInitializingSingleton 接口。如果实现接口会执行该 Bean 的 afterSingletonsInstantiated() 方法。代码如下:
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 将所有BeanDefinition的名字创建一个集合
List beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 触发所有非延迟加载单例bean的初始化,遍历集合的对象
for (String beanName : beanNames) {
// 合并父类BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 条件判断,抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否实现了FactoryBean接口
if (isFactoryBean(beanName)) {
// 根据&+beanName来获取具体的对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 进行类型转换
if (bean instanceof FactoryBean) {
FactoryBean factory = (FactoryBean) bean;
// 判断这个FactoryBean是否希望立即初始化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean) factory).isEagerInit());
}
//如果希望急切的初始化,则通过beanName获取bean实例
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
getBean(beanName);
}
}
}// Trigger post-initialization callback for all applicable beans...
// 遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
for (String beanName : beanNames) {
// 获取beanName对应的bean实例
Object singletonInstance = getSingleton(beanName);
// 判断singletonInstance是否实现了SmartInitializingSingleton接口
if (singletonInstance instanceof SmartInitializingSingleton) {
// 类型转换
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
// 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction