监听器模式是什么?
把广播器(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
- 实现ApplicationListener接口针对单一事件监听
- 实现SmartApplicationListener接口针对单一事件监听