目录
5、疑问:ApplicationEventMulticaster何时初始化?监听器又是何时添加到defaultRetriever里的?
6、ApplicationEventPublisher(实际上就是AbstractApplicationContext)
1、重要角色
(1)ApplicationEvent:发布的事件
(2)ApplicationListener:事件监听器,处理发布的事件
(3)ApplicationEventMulticaster:事件发布者;维护所有已注册的监听器、缓存事件->监听器的映射,让监听器监听并处理对应的事件;multicast可以理解为事件统一在这里发布
(4)ApplicationEventPublisher:发布事件的时候,一般不会直接使用ApplicationEventMulticaster,而是通过ApplicationEventPublisher.publishEvent,再调用ApplicationEventMulticaster发布事件;ApplicationContext就是它的子接口
2、ApplicationEvent
/**
* 一个抽象类,自定义的事件必须继承它
* 继承了EventObject,JDK事件规范的类
*/
public abstract class ApplicationEvent extends EventObject {
/** System time when the event happened */
//事件何时发生
private final long timestamp;
/**
* Create a new ApplicationEvent.
* source:事件源,即事件发生在哪个对象
* @param source the object on which the event initially occurred (never {@code null})
*/
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
}
3、ApplicationListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* 处理一个事件
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
4、ApplicationEventMulticaster
(1)AbstractApplicationEventMulticaster
//实现了基本的监听器注册功能,最关键的multicastEvent方法留给子类实现
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
//ListenerRetriever是定义的一个内部类,可以理解为封装多个监听器的集合
//维护着所有已添加的监听器
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
//ListenerCacheKey是定义的一个内部类,是通过事件+事件源(EventType+SourceType)得出的一个key
//缓存了事件->监听器的1对多映射
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);
//同步操作时的互斥锁
private Object retrievalMutex = this.defaultRetriever;
/**
* 获取指定事件匹配的监听器
* 1、从缓存获取
* 2、缓存没有,遍历defaultRetriever获取并缓存
*/
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
//根据事件类型和事件源类型构建出key
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Quick check for existing entry on ConcurrentHashMap...
//根据key先从缓存查对应的监听器
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.