⑦、Spring-->refresh()--> registerListeners()


前言

     前面我们已经实现了事件多播器,这篇文章registerListeners()的作用是绑定事件多播器和listner的,除此之外我们再看看事件多播器是怎么广播给listner的。

1、 registerListeners()

protected void registerListeners() {
	// Register statically specified listeners first.
	----------首先注册静态指定的监听器。目前getApplicationListeners()为空。
	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的组件
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
	----------①、往当前应用applicationEventMulticaster中添加ApplicationListenerBean
		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);
		}
	}
}

①、往当前应用applicationEventMulticaster(事件多播器)中添加ApplicationListenerBean

getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
==============AbstractApplicationEventMulticaster.java
public void addApplicationListenerBean(String listenerBeanName) {
	synchronized (this.retrievalMutex) {
		this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
		this.retrieverCache.clear();
	}
}

注意:因为regiseterLiseteners()方法是还没有实例化listner的组件的,所以addApplicationListenerBean是往defaultRetriever.applicationListenerBeans中添加listner的名称,
前面在①、Spring AnnotationConfigApplicationContext 源码分析(3) ---->refresh() 大概结构;中的prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)方法中有

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

往beanFactory中添加了ApplicationListenerDetector这个bean后置处理器才会真正往applicationEventMulticaster中添加listner。

ApplicationListenerDetector后置处理器如下:当前listner已经实例化完成,处于初始化属性阶段。

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
	if (this.applicationContext != null && 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
			-------------真正往事件多播器中添加listner.
			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;
}

至此,事件多播器和listner就绑定完成了,或者说事件多播器就添加了listner

2、事件多播器是怎么广播给listner的?

主要调用AbstractApplicationContext中的publishEvent(ApplicationEvent event)

在应用启动过程中,下面执行链会调用publishEvent(ApplicationEvent event)
refresh()->finishRefresh()->publishEvent(new ContextRefreshedEvent(this))代码如下:

publishEvent(new ContextRefreshedEvent(this));
================================
@Override
public void publishEvent(ApplicationEvent event) {
	publishEvent(event, null);
}
================================
protected void publishEvent(Object event, ResolvableType eventType) {
	Assert.notNull(event, "Event must not be null");
	if (logger.isTraceEnabled()) {
		logger.trace("Publishing event in " + getDisplayName() + ": " + event);
	}

	// Decorate event as an ApplicationEvent if necessary
	ApplicationEvent applicationEvent;
	if (event instanceof ApplicationEvent) {
		applicationEvent = (ApplicationEvent) event;
	}
	else {
		applicationEvent = new PayloadApplicationEvent<Object>(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 {
		-----------①、获取当前事件多播器并且广播事件。
		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);
		}
	}
}
============================
@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);
		}
	}
}
=================================================
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
	try {
		最终调用listener的.onApplicationEvent(event)方法。
		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.isDebugEnabled()) {
				logger.debug("Non-matching event type for listener: " + listener, ex);
			}
		}
		else {
			throw ex;
		}
	}
}

我们也可以直接获取当前applicationContext.publishEvent(new ApplicationEvent(“手动发布了一个事件”){});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值