一,先自己实现两个监听器
1.实现ApplicationListener接口,泛型ApplicationStartingEvent,监听starting事件
@Order(1)
public class FirstListener implements ApplicationListener<ApplicationStartingEvent> {
@Override
public void onApplicationEvent(ApplicationStartingEvent event) {
System.out.println("hello FirstListener");
}
}
2.实现SmartApplicationListener接口,在supportsEventType方法中,去匹配需要监听的事件,此处监听starting,started,prepared事件
@Order(4)
public class FourthListener implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return ApplicationStartingEvent.class.isAssignableFrom(eventType) ||ApplicationStartedEvent.class.isAssignableFrom(eventType) || ApplicationPreparedEvent.class.isAssignableFrom(eventType);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("hello FourthListener");
}
}
3.在resources/META-INF/spring.factories 中配置这两个类,key为接口,value为上述两个类,逗号隔开
#监听器配置
org.springframework.context.ApplicationListener=com.mooc.study.event.weather.listener.sb.FirstListener,com.mooc.study.event.weather.listener.sb.FourthListener
二.进入spring boot源码分析
1.分析starting事件,进入starting方法
2.跳转到广播器的广播事件方法multicastEvent
3.进入同名方法,调用getApplicationListeners方法,获取starting事件感兴趣的监听器
4.分析getApplicationListeners方法的源码,核心代码都写上注释,主要看注释
/**
* Return a Collection of ApplicationListeners matching the given
* event type. Non-matching listeners get excluded early.
* @param event the event to be propagated. Allows for excluding
* non-matching listeners early, based on cached matching information.
* @param eventType the event type
* @return a Collection of ApplicationListeners
* @see org.springframework.context.ApplicationListener
*/
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
//获取事件来源
Object source = event.getSource();
//监听的事件类型包装,此次是监听starting事件
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);
if (retriever != null) {
return retriever.getApplicationListeners();
}
retriever = new ListenerRetriever(true);
//核心方法,获取所有感兴趣的事件监听器(这一次是starting事件)
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.分析retrieveApplicationListeners方法源码,获取所有感兴趣的事件监听器(这一次是starting事件),重要代码全部写上注释
/**
* Actually retrieve the application listeners for the given event and source type.
* @param eventType the event type
* @param sourceType the event source type
* @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
* @return the pre-filtered list of application listeners for the given event and source type
*/
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);
}
for (ApplicationListener<?> listener : listeners) {
//核心方法-该监听器是否该事件感兴趣判断
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
//根据order值进行排序
AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
retriever.applicationListeners.clear();
retriever.applicationListeners.addAll(allListeners);
}
return allListeners;
}
6.分析是否是感兴趣监听器方法supportsEvent(listener, eventType, sourceType)方法,回调监听器的supportsEventType方法 ,判断监听器是否对当前的事件感兴趣。如果是FourthListener这个自己实现的监听器则是回调如下方法进行判断
protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
//判断是否是GenericApplicationListener的子类否则进行GenericApplicationListener包装
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
//回调监听器的supportsEventType方法 ,判断监听器是否对当前的事件感兴趣
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
7.最后广播器调用invokeListener(listener, event)方法进行事件执行