亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot深入分析講解監(jiān)聽器模式下

 更新時間:2022年07月15日 10:05:03   作者:lhf2112  
監(jiān)聽器模式,大家應該并不陌生,主要的組成要素包括了事件、監(jiān)聽器以及廣播器;當事件發(fā)生時,廣播器負責將事件傳遞給所有已知的監(jiān)聽器,而監(jiān)聽器會對自己感興趣的事件進行處理

我們來以應用啟動事件:ApplicationStartingEvent為例來進行說明:

以啟動類的SpringApplication.run方法為入口,跟進SpringApplication的兩個同名方法后,我們會看到主要的run方法,方法比較長,在這里只貼出與監(jiān)聽器密切相關的關鍵的部分:

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();

我們跟進這個starting方法,方法的內容如下:

void starting() {
	for (SpringApplicationRunListener listener : this.listeners) {
		listener.starting();
	}
}

這里的listeners已經(jīng)在getRunListeners方法中完成了加載,加載原理類似于系統(tǒng)初始化器,關于系統(tǒng)初始化器的加載可以參考SpringBoot深入淺出分析初始化器

starting方法邏輯很簡單,就是調用SpringApplicationRunListener的starting方法。下面繼續(xù)分析這個starting方法:

我們進入了EventPublishingRunListener類(SpringApplicationRunListener 的實現(xiàn)類)的starting方法:

	@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}

這里就使用了廣播器,來廣播新的ApplicationStartingEvent事件。

我們跟進這個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做了包裝,我們不去關注;由于我們沒有創(chuàng)建線程池,所以executor是空的。我們重點關注兩個部分:

1、getApplicationListeners --> 獲取所有關注此事件的監(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,如果沒有找到,加鎖再從緩存里面找一次。這里我們緩存里是沒有內容的,所以都不會返回。

接下來調用了retrieveApplicationListeners方法,來遍歷所有的監(jiān)聽器。retrieveApplicationListeners方法比較長,我們重點關注下supportsEvent(listener, eventType, sourceType)方法,該方法用來判斷是否此監(jiān)聽器關注該事件,過程主要包括,判斷此類型是否是GenericApplicationListener類型,如果不是,則構造一個代理,代理的目的是,通過泛型解析,最終獲得監(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));
	}

當某個事件所有的監(jiān)聽器被收集完畢后,multicastEvent(SimpleApplicationEventMulticaster類)方法會對事件進行傳播。即調用監(jiān)聽器的通用觸發(fā)接口方法:listener.onApplicationEvent(event);這樣,就完成了這個事件的傳播。

上一篇

到此這篇關于SpringBoot深入分析講解監(jiān)聽器模式下的文章就介紹到這了,更多相關SpringBoot監(jiān)聽器模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java數(shù)組隊列及環(huán)形數(shù)組隊列超詳細講解

    Java數(shù)組隊列及環(huán)形數(shù)組隊列超詳細講解

    隊列是一個有序列表,可以用數(shù)組和鏈表來實現(xiàn),隊列有一個原則。即:先存入隊列的數(shù)據(jù)要先取出,后存入的要后取出,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-09-09
  • JDBC如何獲取數(shù)據(jù)庫連接

    JDBC如何獲取數(shù)據(jù)庫連接

    這篇文章主要為大家詳細為大家詳細介紹了JDBC如何獲取數(shù)據(jù)庫連接,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • java中DelayQueue實例用法詳解

    java中DelayQueue實例用法詳解

    在本篇內容里小編給大家分享的是一篇關于java中DelayQueue實例用法詳解內容,有需要的朋友們可以跟著學習下。
    2021-01-01
  • 剖析Java中在Collection集合中使用contains和remove為什么要重寫equals

    剖析Java中在Collection集合中使用contains和remove為什么要重寫equals

    這篇文章主要介紹了Collection集合的contains和remove方法詳解remove以及相關的經(jīng)驗技巧,通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-09-09
  • SSH框架網(wǎng)上商城項目第14戰(zhàn)之商城首頁UI的設計

    SSH框架網(wǎng)上商城項目第14戰(zhàn)之商城首頁UI的設計

    這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第14戰(zhàn)之商城首頁UI的設計,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Java源碼解析之SortedMap和NavigableMap

    Java源碼解析之SortedMap和NavigableMap

    今天帶大家來學習Java SortedMap和NavigableMap,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • 如何獲取java新IO的Path文件大小

    如何獲取java新IO的Path文件大小

    這篇文章主要介紹了如何獲取java新IO的Path文件大小,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • Gradle的SpringBoot項目構建圖解

    Gradle的SpringBoot項目構建圖解

    這篇文章主要介紹了Gradle的SpringBoot項目構建圖解,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java使用JDBC驅動連接MySQL數(shù)據(jù)庫

    Java使用JDBC驅動連接MySQL數(shù)據(jù)庫

    這篇文章主要為大家詳細介紹了Java使用JDBC驅動連接MySQL數(shù)據(jù)庫的具體步驟,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Java中LambdaQueryWrapper設置自定義排序代碼示例

    Java中LambdaQueryWrapper設置自定義排序代碼示例

    這篇文章主要給大家介紹了關于Java中LambdaQueryWrapper設置自定義排序的相關資料,lambdaquerywrapper是MyBatis-Plus框架中的一個查詢條件構造器,它可以用于構建自定義的查詢條件,需要的朋友可以參考下
    2023-12-12

最新評論