文章目录
前言
前面我们已经实现了事件多播器,这篇文章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(“手动发布了一个事件”){});