Spring中refresh分析之registerListeners方法详解

关联博文:
AbstractApplicationContext中refresh方法详解
Spring中refresh分析之prepareRefresh方法详解
Spring中refresh分析之obtainFreshBeanFactory方法详解
Spring中refresh分析之prepareBeanFactory方法详解
Spring中refresh分析之postProcessBeanFactory方法详解
Spring中refresh分析之invokeBeanFactoryPostProcessors方法详解
Spring中refresh分析之registerBeanPostProcessors方法详解
Spring中refresh分析之initMessageSource方法详解
Spring中refresh分析之initApplicationEventMulticaster方法详解
Spring中refresh分析之onRefresh方法详解
Spring中refresh分析之registerListeners方法详解
Spring中refresh分析之finishBeanFactoryInitialization方法详解
Spring中refresh分析之finishRefresh方法详解

接上文Spring中refresh分析之onRefresh方法详解我们分析过onRefresh后,本文分析registerListeners方法。

顾名思义,注册监听器。将会获取AbstractApplicationContextapplicationListeners和容器中的ApplicationListener进行注册,最后会尝试将earlyApplicationEvents广播出去。

protected void registerListeners() {
	// Register statically specified listeners first.
	//获取的是成员applicationListeners
	for (ApplicationListener<?> listener : getApplicationListeners()) {
	// 获取SimpleApplicationEventMulticaster触发其方法
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let post-processors apply to them!
	// 从容器中获取ApplicationListener
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		// 获取SimpleApplicationEventMulticaster触发其方法-这里放的是beanName
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// Publish early application events now that we finally have a multicaster...
	// 发布早期事件,本文这里为空
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;

	//设置为null,这个很重要
	this.earlyApplicationEvents = null;
	if (earlyEventsToProcess != null) {
	// 如果早期/渴望的事件存在,则将其广播出去
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

方法逻辑梳理如下:

  • 获取AbstractApplicationContext的成员监听器然后遍历进行注册;
  • 从容器中获取ApplicationListener然后进行遍历记录监听器名称放到this.defaultRetriever.applicationListenerBeans
  • earlyApplicationEvents赋予earlyEventsToProcess 然后重新将置为null。如果earlyEventsToProcess不为空则进行遍历挨个进行事件广播。

这里getApplicationListeners()获取的applicationListenersAbstractApplicationContext的成员private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();。这些监听器是在refresh方法前的prepareContext方法中注册进来的。

earlyApplicationEvents我们在哪里看到过呢?仍然是prepareRefresh方法中,对其进行了初始化是一个空的LinkedHashSet。

在这里插入图片描述
通过应用上下文广播事件时,如果事件广播器还没有实例化好,那么事件会被存放在earlyApplicationEvents中。当事件广播器实例化好之后,earlyApplicationEvents会被指向null,其维护的早期事件会被广播出去。


addApplicationListener

我们继续看SimpleApplicationEventMulticasteraddApplicationListener方法,看是如何对监听器进行注册的。

@Override
public void addApplicationListener(ApplicationListener<?> listener) {
	synchronized (this.retrievalMutex) {
		// Explicitly remove target for a proxy, if registered already,
		// in order to avoid double invocations of the same listener.
		Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
		if (singletonTarget instanceof ApplicationListener) {
			this.defaultRetriever.applicationListeners.remove(singletonTarget);
		}
		this.defaultRetriever.applicationListeners.add(listener);
		// 检索缓存,是一个ConcurrentHashMap
		this.retrieverCache.clear();
	}
}

方法逻辑梳理如下:

  • 如果listener是一个代理,则尝试获取其原始对象。如果获取到的原理对象为ApplicationListener则从defaultRetriever.applicationListeners移除;
  • 否则放入defaultRetriever.applicationListeners
  • 清理retrieverCache

defaultRetrieverListenerRetriever类型,内部维护了applicationListeners 集合。本文这里的defaultRetrieverAbstractApplicationEventMulticaster的成员。

private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);

private class ListenerRetriever {
	//记录监听器实例
	public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
	// 记录监听器名称
	public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
	private final boolean preFiltered;
	//...
}

getSingletonTarget

getSingletonTarget是获取代理对象后面的单例目标对象()原始对象。如下所示如果是Advised且存在SingletonTargetSource类型的targetSource 则返回targetSource的target对象。否则返回null。

public static Object getSingletonTarget(Object candidate) {
	if (candidate instanceof Advised) {
		TargetSource targetSource = ((Advised) candidate).getTargetSource();
		if (targetSource instanceof SingletonTargetSource) {
			return ((SingletonTargetSource) targetSource).getTarget();
		}
	}
	return null;
}

applicationListeners本文这里有17个监听器(记录的是AbstractApplicationContext的成员):

0 = {ConditionEvaluationReportLoggingListener$ConditionEvaluationReportListener@3203} 
1 = {RSocketPortInfoApplicationContextInitializer$Listener@6339} 
2 = {ServerPortInfoApplicationContextInitializer@6340} 
3 = {RestartApplicationListener@6341} 
4 = {CloudFoundryVcapEnvironmentPostProcessor@6342} 
5 = {ConfigFileApplicationListener@6343} 
6 = {AnsiOutputApplicationListener@6344} 
7 = {LoggingApplicationListener@6345} 
8 = {BackgroundPreinitializer@6346} 
9 = {ClasspathLoggingApplicationListener@6347} 
10 = {DelegatingApplicationListener@6348} 
11 = {ParentContextCloserApplicationListener@6349} 
12 = {DevToolsLogFactory$Listener@6350} 
13 = {ClearCachesApplicationListener@3672} 
14 = {FileEncodingApplicationListener@3695} 
15 = {LiquibaseServiceLocatorApplicationListener@6351} 
16 = {SharedMetadataReaderFactoryContextInitializer$SharedMetadataReaderFactoryBean@6352} 

applicationListenerBeans有如下11个(记录的是容器中的):

0 = "&org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
1 = "cachingModelPropertiesProvider"
2 = "objectMapperBeanPropertyNamingStrategy"
3 = "optimized"
4 = "delegatingApplicationListener"
5 = "mvcResourceUrlProvider"
6 = "org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker"
7 = "springApplicationAdminRegistrar"
8 = "restartingClassPathChangedEventListener"
9 = "conditionEvaluationDeltaLoggingListener"
10 = "liveReloadServerEventListener"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值