最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

我們來以應(yīng)用啟動(dòng)事件:ApplicationStartingEvent為例來進(jìn)行說明:

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

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

我們跟進(jìn)這個(gè)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ù)分析這個(gè)starting方法:

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

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

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

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

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類型本人將其視作是一個(gè)保存監(jiān)聽器的容器。

可以看出,程序首先在緩存里面尋找ListenerRetriever類型的retriever,如果沒有找到,加鎖再從緩存里面找一次。這里我們緩存里是沒有內(nèi)容的,所以都不會(huì)返回。

接下來調(diào)用了retrieveApplicationListeners方法,來遍歷所有的監(jiān)聽器。retrieveApplicationListeners方法比較長,我們重點(diǎn)關(guān)注下supportsEvent(listener, eventType, sourceType)方法,該方法用來判斷是否此監(jiān)聽器關(guān)注該事件,過程主要包括,判斷此類型是否是GenericApplicationListener類型,如果不是,則構(gòu)造一個(gè)代理,代理的目的是,通過泛型解析,最終獲得監(jiān)聽器所感興趣的事件。

如果經(jīng)過判斷,監(jiān)聽器對(duì)該事件是感興趣的,則此監(jiān)聽器會(huì)被加入監(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)某個(gè)事件所有的監(jiān)聽器被收集完畢后,multicastEvent(SimpleApplicationEventMulticaster類)方法會(huì)對(duì)事件進(jìn)行傳播。即調(diào)用監(jiān)聽器的通用觸發(fā)接口方法:listener.onApplicationEvent(event);這樣,就完成了這個(gè)事件的傳播。

上一篇

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

相關(guān)文章

  • Springboot之如何統(tǒng)計(jì)代碼執(zhí)行耗時(shí)時(shí)間

    Springboot之如何統(tǒng)計(jì)代碼執(zhí)行耗時(shí)時(shí)間

    這篇文章主要介紹了Springboot之如何統(tǒng)計(jì)代碼執(zhí)行耗時(shí)時(shí)間問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java 讀取文件路徑空格、

    java 讀取文件路徑空格、"+"和中文的處理方法

    今天小編就為大家分享一篇java 讀取文件路徑空格、"+"和中文的處理方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • 使用BigDecimal除法后保留兩位小數(shù)

    使用BigDecimal除法后保留兩位小數(shù)

    這篇文章主要介紹了使用BigDecimal除法后保留兩位小數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java中documentHelper解析xml獲取想要的數(shù)據(jù)

    Java中documentHelper解析xml獲取想要的數(shù)據(jù)

    本文主要介紹了Java中documentHelper解析xml獲取想要的數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • java使用任務(wù)架構(gòu)執(zhí)行任務(wù)調(diào)度示例

    java使用任務(wù)架構(gòu)執(zhí)行任務(wù)調(diào)度示例

    在Java 5.0之前啟動(dòng)一個(gè)任務(wù)是通過調(diào)用Thread類的start()方法來實(shí)現(xiàn)的,5.0里提供了一個(gè)新的任務(wù)執(zhí)行架構(gòu)使你可以輕松地調(diào)度和控制任務(wù)的執(zhí)行,并且可以建立一個(gè)類似數(shù)據(jù)庫連接池的線程池來執(zhí)行任務(wù),下面看一個(gè)示例
    2014-01-01
  • Java中Steam流的用法詳解

    Java中Steam流的用法詳解

    Stream是Java?8?API添加的一個(gè)新的抽象,稱為流Stream,本文主要介紹了Java中Steam流的用法詳解,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-04-04
  • SpringMVC4.3?HandlerExceptionResolver異常處理源碼解析

    SpringMVC4.3?HandlerExceptionResolver異常處理源碼解析

    這篇文章主要為大家介紹了SpringMVC4.3?HandlerExceptionResolver異常處理源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2023-09-09
  • java中實(shí)現(xiàn)list或set轉(zhuǎn)map的方法

    java中實(shí)現(xiàn)list或set轉(zhuǎn)map的方法

    這篇文章主要介紹了java中實(shí)現(xiàn)list或set轉(zhuǎn)map的方法的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • Spring框架學(xué)習(xí)之Cache抽象詳解

    Spring框架學(xué)習(xí)之Cache抽象詳解

    這篇文章主要為大家介紹了Spring框架學(xué)習(xí)中Cache抽象詳解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • SpringMVC+MyBatis實(shí)現(xiàn)多數(shù)據(jù)源切換

    SpringMVC+MyBatis實(shí)現(xiàn)多數(shù)據(jù)源切換

    在企業(yè)級(jí)應(yīng)用開發(fā)中,經(jīng)常需要處理來自不同數(shù)據(jù)庫的數(shù)據(jù),為了滿足這一需求,我們可以通過配置多個(gè)數(shù)據(jù)源來實(shí)現(xiàn)對(duì)不同數(shù)據(jù)庫的訪問,下面我們來看看具體實(shí)現(xiàn)吧
    2025-01-01

最新評(píng)論

铜梁县| 静宁县| 牡丹江市| 连云港市| 哈巴河县| 沅江市| 读书| 金秀| 长宁县| 奉化市| 兰考县| 葫芦岛市| 田林县| 东丰县| 高密市| 花垣县| 绍兴市| 靖西县| 江北区| 桂林市| 基隆市| 健康| 砀山县| 苍南县| 汪清县| 永嘉县| 临城县| 长阳| 陇南市| 会东县| 修武县| 巴东县| 桂平市| 定南县| 舞阳县| 南皮县| 朝阳县| 酒泉市| 长乐市| 三原县| 含山县|