91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot監聽器模式怎么實現

發布時間:2022-07-15 13:55:21 來源:億速云 閱讀:209 作者:iii 欄目:開發技術

本篇內容介紹了“SpringBoot監聽器模式怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

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

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

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

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

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

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

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

我們進入了EventPublishingRunListener類(SpringApplicationRunListener 的實現類)的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));
	}

繼續看同名的方法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做了包裝,我們不去關注;由于我們沒有創建線程池,所以executor是空的。我們重點關注兩個部分:

1、getApplicationListeners --> 獲取所有關注此事件的監聽器(※);

2、invokeListener --> 激活監聽器;

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);
		}
	}

入參中的event就是ApplicationStartingEvent,sourceType是org.springframework.boot.SpringApplication類。ListenerRetriever類型本人將其視作是一個保存監聽器的容器。

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

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

如果經過判斷,監聽器對該事件是感興趣的,則此監聽器會被加入監聽器列表中。

	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));
	}

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

“SpringBoot監聽器模式怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

逊克县| 沾化县| 夹江县| 兰西县| 南皮县| 白河县| 南岸区| 西盟| 绵阳市| 南溪县| 武清区| 四会市| 固阳县| 建瓯市| 永登县| 灌云县| 凌云县| 若尔盖县| 始兴县| 冕宁县| 玛纳斯县| 武乡县| 徐水县| 巴彦淖尔市| 西昌市| 余庆县| 永城市| 七台河市| 榆社县| 沙河市| 麻江县| 义乌市| 四子王旗| 华阴市| 河东区| 榕江县| 安庆市| 青神县| 敦化市| 治多县| 南平市|