监听器模式是什么?

把广播器(caster)想象成一个商场, 每个监听器(listener)是一个商家, 每个事件(event)是一个顾客. 顾客进入商场, 商场遍历商家看哪些能接待这位客人. 最终会将客人交给某些商家接待.

SpringBoot中事件发送顺序

st=>start: Start
o1=>operation: starting
o2=>operation: environmentPrepared
o3=>operation: contextInitialized
o4=>operation: prepared
o5=>operation: started
o6=>operation: ready
e=>end

st->o1->o2->o3->o4->o5->o6->e

SpringBoot监听器实现

//1. 一个事件监听器接口, 没有任何方法, 仅用来表明是事件监听器
public interface EventListener {
}
//2. FunctionalInterface: 接口仅有一个方法, E extends ApplicationEvent: 泛型, 监听到事件后执行onApplicationEvent方法
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	void onApplicationEvent(E event);

}
//3. 系统广播器
public interface ApplicationEventMulticaster {
addApplicationListener
multicastEvent
removeAllListeners
removeApplicationListener
}
//4. 系统事件介绍
//EventObject>ApplicationEvent>SpringApplicationEvent>(各种具体事件)
//5. 事件发送顺序
//starting>environmentPrepared>ContextInitialized>prepared>started>ready
//如果失败, 就发送failed

监听器的底层实现

相对初始化器, 监听器的实现就繁复许多, 在多个方法中跳转, 没有那么容易理解. 但梳理清楚脉络后, 也没有太过于复杂的逻辑.

    //1. 发布starting事件
	void starting() {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}
	//2. 创建开始事件,并广播
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}
	//3. 计算该事件的ResolvableType, 并找出所有对该事件感兴趣的监听器执行该事件
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		//获取线程池
		Executor executor = getTaskExecutor();
		//获取所有对该事件感兴趣的监听器
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
		//有线程池就用线程池
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
			//没线程池就直接调用
				invokeListener(listener, event);
			}
		}
	}
	//4. Return a Collection of ApplicationListeners matching the given event type.
		protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {

        //首先查询缓存
		Object source = event.getSource();
		Class<?> sourceType = (source != null ? source.getClass() : null);
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

		// Quick check for existing entry on ConcurrentHashMap...
		ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
		if (retriever != null) {
			return retriever.getApplicationListeners();
		}

		if (this.beanClassLoader == null ||
				(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
						(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
			// Fully synchronized building and caching of a ListenerRetriever, 构建并缓存监听器
			synchronized (this.retrievalMutex) {
			//再次确认缓存中没有对应的
				retriever = this.retrieverCache.get(cacheKey);
				//直接从容器中拿listeners
				if (retriever != null) {
					return retriever.getApplicationListeners();
				}
				retriever = new ListenerRetriever(true);
			//Actually retrieve the application listeners for the given event and source type.	Collection<ApplicationListener<?>> listeners =
						retrieveApplicationListeners(eventType, sourceType, retriever);
				this.retrieverCache.put(cacheKey, retriever);
				return listeners;
			}
		}
		else {
			// No ListenerRetriever caching -> no synchronization necessary
			return retrieveApplicationListeners(eventType, sourceType, null);
		}
	}
	
	//5. 真实得一个一个获取监听器
	private Collection<ApplicationListener<?>> retrieveApplicationListeners(
			ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {

		List<ApplicationListener<?>> allListeners = new ArrayList<>();
		Set<ApplicationListener<?>> listeners;
		Set<String> listenerBeans;
		synchronized (this.retrievalMutex) {
			listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
			listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
		}

		// Add programmatically registered listeners, including ones coming
		// from ApplicationListenerDetector (singleton beans and inner beans).
		for (ApplicationListener<?> listener : listeners) {
		//如果该监听器支持该事件
			if (supportsEvent(listener, eventType, sourceType)) {
				if (retriever != null) {
					retriever.applicationListeners.add(listener);
				}
				allListeners.add(listener);
			}
		}

		AnnotationAwareOrderComparator.sort(allListeners);
		if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
			retriever.applicationListeners.clear();
			retriever.applicationListeners.addAll(allListeners);
		}
		return allListeners;
	}	
	//6. 判断是否支持事件
	protected boolean supportsEvent(
			ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
        //创建smartListener, 如果监听器是GenericApplicationListener的实例, 就直接赋值, 否则赋值适配器适配后的监听器
		GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
				(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
		//判断监听器是否支持该事件类型及source类型
		return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
	}

获取监听器列表流程

st=>start: Start
o1=>operation: getApplicationListeners
o2=>operation: retrieveApplicationListeners
o3=>operation: loop listeners
o4=>operation: add corresponding listeners

c1=>condition: cached?
c2=>condition: supportsEvent?

e=>end

st->o1->c1
c1(no)->o2->o3->c2
c2(yes)->o4->e

通用触发条件

st=>start: Start
e=>end

o1=>operation: supportsEventTypes
o2=>operation: supportsSourceTypes

c1=>condition: SmartApplicationListener?
c2=>condition: supportsEventType?
c3=>condition: 实现接口类变量是否事件同类或子类?
c4=>condition: SmartApplicationListener?
c5=>condition: 实现类是否supportsSourceType?


st->o1->c1
c1(yes)->c2
c1(no)->c3
c2(yes)->o2
c3(yes)->o2
o2->c4
c4(yes)->c5
c4(no)->e
c5(yes)->e

Tips

  1. 实现ApplicationListener接口针对单一事件监听
  2. 实现SmartApplicationListener接口针对单一事件监听