【一】相關原始碼類
(1)spring的事件釋出監聽機制的核心管理類:org.springframework.context.event.SimpleApplicationEventMulticaster.
=>該類的初始化是放在專案載入時,在ioc容器xml配置檔案解析載入完畢後,註冊bean建立前後置處理實現類(BeanPostProcessor 介面實現),beanFactory配置處理(BeanFactoryPostProcessor介面實現)後,初始化該事件釋出監聽機制的核心類。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// 解析xml配置檔案
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 註冊未來bean例項化的前後置處理的PostProcessor介面實現
postProcessBeanFactory(beanFactory);
//執行所有實現BeanFactoryPostProcessor介面實現,對beanFactory進行處理
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊未來bean例項化的前後置處理的PostProcessor介面實現
registerBeanPostProcessors(beanFactory);
// 註冊未來bean例項化的前後置處理的PostProcessor介面實現
initMessageSource();
// 例項化spring事件釋出監聽機制的核心類,SimpleApplicationEventMulticaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 註冊事件監聽器
registerListeners();
// 例項化非懶載入的bean,完成ioc容器中bean的例項化和反轉依賴,並在內部實現動態代理相關的操作
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
View Code
(2)spring的事件釋出監聽機制的監聽器類的介面:org.springframework.context.ApplicationListener<E extends ApplicationEvent>
=>監聽器的定義必須實現該介面。
=>所監聽的事件也必須繼承org.springframework.context.ApplicationEvent的抽象類
=>在初始化管理類後,會註冊監聽器。會從beanFactory裡得到所有實現ApplicationListener介面的bean的名字,並註冊到ListenerRetriever的屬性applicationListenerBeans集合中。
(3)spring的事件釋出監聽機制的事件的基礎類:org.springframework.context.ApplicationEvent
=>事件的事件類必須繼承該基類
=>定義監聽器的同時,必須定義相關的事件類。
(4)spring的事件釋出監聽機制的儲存事件監聽的類:org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerRetriever
=>該類內部儲存了一個n個事件對應的多個監聽器
=>屬性Set<ApplicationListener<?>> applicationListeners 儲存的是事件監聽器的例項
=>屬性Set<String> applicationListenerBeans 儲存的事件監聽器在ioc容器中的beanNames
(5)spring的事件釋出監聽機制的儲存事件體的類:org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerCacheKey
=>一個事件體的class型別+事件源(事件體記憶體儲的資料)的class型別決定由那些監聽監聽器處理該事件
=>屬性Class<?> eventType 儲存的事件體的class型別
=>屬性Class<?> sourceType 儲存的事件源的class型別(事件體內資料)
【二】設計思想
(1)透過事件體,拿到事件類的cls1型別,和事件源(事件體內部儲存的資料類)的cls型別
(2)然後在IOC容器中所有實現ApplicationListener介面的事件監聽器中進行匹配。找到所有適合該事件的事件監聽器集合。將事件監聽集合形成ListenerRetriever物件。
=>從IOC容器中的一個個事件監聽器實現類的範型填充類的型別(也就是事件體的 型別)cls2
=>Listener可能是代理物件(因為@Async註解),Listenner的ioc在例項化階段,會被spring建立成代理物件。spring內部也會做處理,得到代理物件代理的targetClass,也就是Listenner的真實型別。
=>看當前事件體的型別cls1是否是事件監聽器的範型填充類的型別cls2的子類或本身。如果是,則表示這個事件監聽器匹配該事件。
(3)將該事件體,的事件類的cls1型別+事件源的cls型別。形成ListenerCacheKey物件,以此為key,以事件監聽集合ListenerRetriever物件作為value,儲存在AbstractApplicationEventMulticaster類中private final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);屬性中作為cache,方便下次匹配,不再從ioc容器中重新匹配。
【三】事件緩衝,擴充套件。hasMap中以物件作為key。需要重寫hasCode方法,equals方法
private static class ListenerCacheKey {
private final Class<?> eventType;
private final Class<?> sourceType;
public ListenerCacheKey(Class<?> eventType, Class<?> sourceType) {
this.eventType = eventType;
this.sourceType = sourceType;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
ListenerCacheKey otherKey = (ListenerCacheKey) other;
return ObjectUtils.nullSafeEquals(this.eventType, otherKey.eventType) &&
ObjectUtils.nullSafeEquals(this.sourceType, otherKey.sourceType);
}
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.eventType) * 29 + ObjectUtils.nullSafeHashCode(this.sourceType);
}
}
View Code