您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“SpringBoot監(jiān)聽器模式怎么實現(xiàn)”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
我們來以應(yīng)用啟動事件:ApplicationStartingEvent為例來進(jìn)行說明:
以啟動類的SpringApplication.run方法為入口,跟進(jìn)SpringApplication的兩個同名方法后,我們會看到主要的run方法,方法比較長,在這里只貼出與監(jiān)聽器密切相關(guān)的關(guān)鍵的部分:
SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting();
我們跟進(jìn)這個starting方法,方法的內(nèi)容如下:
void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } }
這里的listeners已經(jīng)在getRunListeners方法中完成了加載,加載原理類似于系統(tǒng)初始化器,關(guān)于系統(tǒng)初始化器的加載可以參考SpringBoot深入淺出分析初始化器
starting方法邏輯很簡單,就是調(diào)用SpringApplicationRunListener的starting方法。下面繼續(xù)分析這個starting方法:
我們進(jìn)入了EventPublishingRunListener類(SpringApplicationRunListener 的實現(xiàn)類)的starting方法:
@Override public void starting() { this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args)); }
這里就使用了廣播器,來廣播新的ApplicationStartingEvent事件。
我們跟進(jìn)這個multicastEvent方法:
@Override public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); }
繼續(xù)看同名的方法multicastEvent:
@Override 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); } } }
這里的ResolvableType 是對event做了包裝,我們不去關(guān)注;由于我們沒有創(chuàng)建線程池,所以executor是空的。我們重點關(guān)注兩個部分:
1、getApplicationListeners --> 獲取所有關(guān)注此事件的監(jiān)聽器(※);
2、invokeListener --> 激活監(jiān)聽器;
getApplicationListeners (AbstractApplicationEventMulticaster類中)方法,代碼如下:
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); if (retriever != null) { return retriever.getApplicationListeners(); } retriever = new ListenerRetriever(true); 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); } }
入?yún)⒅械膃vent就是ApplicationStartingEvent,sourceType是org.springframework.boot.SpringApplication類。ListenerRetriever類型本人將其視作是一個保存監(jiān)聽器的容器。
可以看出,程序首先在緩存里面尋找ListenerRetriever類型的retriever,如果沒有找到,加鎖再從緩存里面找一次。這里我們緩存里是沒有內(nèi)容的,所以都不會返回。
接下來調(diào)用了retrieveApplicationListeners方法,來遍歷所有的監(jiān)聽器。retrieveApplicationListeners方法比較長,我們重點關(guān)注下supportsEvent(listener, eventType, sourceType)方法,該方法用來判斷是否此監(jiān)聽器關(guān)注該事件,過程主要包括,判斷此類型是否是GenericApplicationListener類型,如果不是,則構(gòu)造一個代理,代理的目的是,通過泛型解析,最終獲得監(jiān)聽器所感興趣的事件。
如果經(jīng)過判斷,監(jiān)聽器對該事件是感興趣的,則此監(jiān)聽器會被加入監(jiān)聽器列表中。
protected boolean supportsEvent( ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) { GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ? (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); }
當(dāng)某個事件所有的監(jiān)聽器被收集完畢后,multicastEvent(SimpleApplicationEventMulticaster類)方法會對事件進(jìn)行傳播。即調(diào)用監(jiān)聽器的通用觸發(fā)接口方法:listener.onApplicationEvent(event);這樣,就完成了這個事件的傳播。
“SpringBoot監(jiān)聽器模式怎么實現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。