ApplicationListener 源码解读

缘起

我们知道Spring提供了ApplicationListener接口给我们在容器中发布事件. 其实Spring IOC容器自己也发布事件——至少容器初始化(refresh)成功之后以及关闭之前会发布开启与关闭的事件. 此时我们就可以使用自定义的ApplicationListener来接收事件. 本文debug用的demo【1】

分析

其实,不难想象用的设计模式是发布订阅模式(说白了就是回调订阅者的接口). 下面分析源码.

首先,【1】中我们将收到三种事件

  1. ContextRefreshedEvent,ioc容器refresh成功
  2. ContextClosedEvent, ioc容器关闭前
  3. 自定义发布的事件, 显式调用容器的publishEvent接口.

第一个事件的调用栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
...
refresh();
}
-->
refresh方法中的
// Last step: publish corresponding event.
finishRefresh();
-->
org.springframework.context.support.AbstractApplicationContext.finishRefresh()
protected void finishRefresh() {
...
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
...
}
-->
org.springframework.context.support.AbstractApplicationContext.publishEvent(Object, ResolvableType)
...
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
...

​ 源码1

到上面的21行,getApplicationEventMulticaster()做的事情是获取容器中的事件多播器. 而multicastEvent就是利用拿到的多播器回调监听器的消息接口. 不信? 我们继续跟源码1的20行

org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(ApplicationEvent, ResolvableType)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}

​ 源码2

这里可以看出,是循环遍历取出所有的监听器(通过源码2的第四行的getApplicationListeners),而且如果有taskExecutor的话,因为源码2的第五行的getTaskExecutor的源码如下

org.springframework.context.event.SimpleApplicationEventMulticaster.getTaskExecutor()

1
2
3
protected Executor getTaskExecutor() {
return this.taskExecutor;
}

​ 源码3

其中taskExecutor实现的是Executor接口,而这个接口有SyncTaskExecutor实现类和AsyncTaskExecutor子接口. 也就是我们如果有taskExecutor的话,可以使用它进行事件的同步或者异步的广播. 否则的话,就同步执行源码2第15行, 跟几步,来到了

org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(ApplicationListener, ApplicationEvent)

1
2
3
4
5
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
...

​ 源码4

源码3做的事情就是回调监听器的onApplicationEvent接口.

至于自定义事件,原理还是一样,但是走的调用栈和上面不同

1
2
3
4
5
6
7
8
9
10
// 自己发布事件
annotationConfigApplicationContext.publishEvent(new ApplicationEvent(new String("我发布了一个事件")) {
});
-->
org.springframework.context.support.AbstractApplicationContext.publishEvent(ApplicationEvent)
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
-->源码1的第20

​ 源码5

后面就和ContextRefreshedEvent一模一样了.

至于ContextClosedEvent事件. 其调用栈如下

1
2
3
4
5
6
7
8
9
10
annotationConfigApplicationContext.close();
-->
org.springframework.context.support.AbstractApplicationContext.close()
doClose();
-->
org.springframework.context.support.AbstractApplicationContext.doClose()
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
-->
源码1的第20

后面就和前面的ContextRefreshedEvent一模一样了.

好了,事件发布的工作原理已经解释清楚了——其实类似于观察者模式. 核心代码就是源码1的第20行.

所以我们就好奇了——源码1的第20行用来工作的两个核心

  1. ApplicationEventMulticaster (广播器)是怎么来的
  2. 监听器怎么来的.

为了回答这两个问题,我们来到

org.springframework.context.support.AbstractApplicationContext.refresh()

里面有两行代码值得注意

1
2
3
4
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Check for listener beans and register them.
registerListeners();

​ 源码6

其中源码6的第二行就是用于注册ApplicationEventMulticaster 的,而源码6的第4行就是用于注册监听器(ApplicationListener)的.

跟进源码6的第二行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}

​ 源码7

源码7做的事情其实很简单——就是判断容器(beanFactory,它是DefaultListableBeanFactory,即ConfigurableListableBeanFactory接口的实现类)中有没有一个id为applicationEventMulticaster的bean,如果有的话,则使用它(所以我们可以定制它,用BeanDefinitionRegistryPostProcessor,这个接口的源码可以参见我之前写的文章).如果没有的话,直接new了一个SimpleApplicationEventMulticaster放进内存中,并且将其注入了beanFactory(IOC容器中). 所以其实我们可以在自定义组件中通过 @Autowired 注入这个ApplicationEventMulticaster (接口)组件的.

于是,ApplicationEventMulticaster 怎么来的我们就清楚了.

下面我们来回答一下第二个问题——监听器是怎么来的. 这就要跟进源码6的第四行.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);
}
}
}

​ 源码8

显然,核心代码就是

1
getApplicationEventMulticaster().addApplicationListener(listener);

即获取上面解释好的ApplicationEventMulticaster之后(已经存在并注册到ioc容器中去了),然后作为其某种意义下的属性加入listener

首先源码8的第三行是不会得到有值的,即第三行的 getApplicationListeners() 得到的一定是空数组.

因为现在还没有发现ApplicationListener嘛~

所以来到源码8的第九行,从getBeanNamesForType名字就可以看出是找ioc中的ApplicationListener类型. 事实上,源码也是这样的

org.springframework.context.support.AbstractApplicationContext.getBeanNamesForType(Class<?>, boolean, boolean)

1
2
3
4
5
@Override
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
assertBeanFactoryActive();
return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}

​ 源码9

第四行的getBeanFactory()拿到ioc容器,然后进到

org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(Class<?>, boolean, boolean)

1
2
3
4
5
6
@Override
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
...

​ 源码10

然后源码10的第四行跟进去就是

org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(ResolvableType, boolean, boolean)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<String>();

// Check all bean definitions.
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
if (!isAlias(beanName)) {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
if (!mbd.isAbstract() && (allowEagerInit ||
((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
boolean isFactoryBean = isFactoryBean(beanName, mbd);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
boolean matchFound =
(allowEagerInit || !isFactoryBean ||
(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
(includeNonSingletons ||
(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
isTypeMatch(beanName, type);
if (!matchFound && isFactoryBean) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
catch (BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
}
}

​ 源码11

注意源码11的的23行的isTypeMatch方法,就是判断是不是 ApplicationListener. 所以最后回到源码8的第10行,就往既有的ApplicationEventMulticaster中添加了我们的ApplicationListener.

DEMO

【1】https://github.com/yfsyfs/backend/tree/master/spring-annotation-applicationlistener