日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言

前一段時間,剛剛接手一個項目,項目中看到使用的spring的事件監(jiān)聽機制,加上之前自己看spring源碼的時候也對spring listener 有點影像,于是就重新追一追源碼,理一理spring 事件監(jiān)聽機制的工作原理

案例

  1. 自定義event
spring監(jiān)聽機制

 

  1. 自定義listener
spring監(jiān)聽機制

 

  1. 測試推送
spring監(jiān)聽機制

 

  1. 測試結(jié)果
spring監(jiān)聽機制

 

一個非常簡單的案例,通過定義事件,監(jiān)聽,推送實現(xiàn)了簡單的事件監(jiān)聽的流程。

原理分析

  1. 推送事件

通過案例可以看到我們通過
ApplicationContext.publishEvent方法來推送事件,實際是其子類 AbstractApplicationContext 實現(xiàn)的發(fā)送操作

spring監(jiān)聽機制

 

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}

通過源碼可以看到發(fā)送事件最終是交個
ApplicationEventMulticaster來推送。

那么
ApplicationEventMulticaster對象是怎么來的呢,它里面具體是如何推送的呢?我們接著往下看。

讀過spring源碼的同學一定對
AbstractApplicationContext中的refresh方法很熟悉。這是spring源碼的核心部分,而在其中有一步

spring監(jiān)聽機制

 

就是來構(gòu)造
ApplicationEventMulticaster。

spring監(jiān)聽機制

 

參照源碼,我們并沒有定義和注冊
applicationEventMulticaster,所以就會使用SimpleApplicationEventMulticaster。

spring監(jiān)聽機制

 

在multicastEvent中

1,首先是ResolvableType的確認

spring監(jiān)聽機制

 


spring監(jiān)聽機制

 

可以看到最后是通過Event的class對象作為ResolvableType的屬性,后面匹配Listener的時候就是使用這個。

2,通過ResolvableType獲取適合的Listener

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);
// Potential new retriever to populate
CachedListenerRetriever newRetriever = null;
// Quick check for existing entry on ConcurrentHashMap
CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey);
if (existingRetriever == null) {
// Caching a new ListenerRetriever if possible
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
newRetriever = new CachedListenerRetriever();
existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
if (existingRetriever != null) {
newRetriever = null; // no need to populate it in retrieveApplicationListeners
}
}
}
if (existingRetriever != null) {
Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
if (result != null) {
return result;
}
// If result is null, the existing retriever is not fully populated yet by another thread.
// Proceed like caching wasn't possible for this current local attempt.
}
return retrieveApplicationListeners(eventType, sourceType, newRetriever);
}

這邊這種使用緩存機制的代碼,可以在spring源碼中多次看到,所以大家可以學習這種方式,提高性能。


retrieveApplicationListeners方法比較大,我這邊只截取了部分,可以看到是通過eventType

和sourceType來獲取適合的listener。

spring監(jiān)聽機制

 

3,接下來就是調(diào)用invokeListener方法來實際操作,這邊可以看到可以通過Executor

來實現(xiàn)異步操作。當然比較好的方式還是自己配置線程池,這樣可以通過前綴區(qū)分出業(yè)務。

spring監(jiān)聽機制

 


spring監(jiān)聽機制

 

至此可以看到,調(diào)用的是對應listener的onApplicationEvent。

分享到:
標簽:spring
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定