ホームページ Java &#&チュートリアル SpringBootリスナーモードの実装方法

SpringBootリスナーモードの実装方法

May 20, 2023 pm 07:07 PM
springboot

アプリケーションの起動イベント ApplicationStartingEvent を例として説明します。

起動クラスの SpringApplication.run メソッドをエントリ ポイントとして取り、SpringApplication の同じ名前の 2 つのメソッドに従います。メインの run メソッドを見ていきます。このメソッドは比較的長いです。ここでは、リスナーに密接に関連する重要な部分だけを掲載します。

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
ログイン後にコピー

開始メソッドをフォローアップします。メソッドの内容は次のとおりです。

void starting() {
	for (SpringApplicationRunListener listener : this.listeners) {
		listener.starting();
	}
}
ログイン後にコピー

Here リスナーは getRunListeners メソッドにロードされています。ロードの原則はシステム イニシャライザと同様です。システム イニシャライザのロードについては、SpringBoot のイニシャライザの詳細な分析を参照してください

開始メソッドのロジックは非常に単純で、SpringApplicationRunListener の開始メソッドを呼び出すだけです。この開始メソッドの分析を続けましょう。

EventPublishingRunListener クラス (SpringApplicationRunListener の実装クラス) の開始メソッドを入力します。

	@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 はイベントをラップします。料金は発生しません。スレッド プールを作成していないため、エグゼキュータは空であることに注意してください。

このイベントをリッスンしているすべてのアプリケーション リスナーを取得します

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);
		}
	}
ログイン後にコピー

入力パラメータのイベントは ApplicationStartingEvent で、sourceType は org.springframework.boot.SpringApplication クラスです。私はListenerRetriever型をリスナーを格納するコンテナと考えています。

プログラムはまずキャッシュ内で ListenerRetriever 型の取得者を探し、見つからない場合はロックしてキャッシュから再度検索することがわかります。ここのキャッシュにはコンテンツがないため、返されません。

次に、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リスナーモードの実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットな記事タグ

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Springboot が Jasypt を統合して構成ファイルの暗号化を実装する方法 Springboot が Jasypt を統合して構成ファイルの暗号化を実装する方法 Jun 01, 2023 am 08:55 AM

Springboot が Jasypt を統合して構成ファイルの暗号化を実装する方法

Redis を使用して SpringBoot に分散ロックを実装する方法 Redis を使用して SpringBoot に分散ロックを実装する方法 Jun 03, 2023 am 08:16 AM

Redis を使用して SpringBoot に分散ロックを実装する方法

SpringBoot が Redisson を統合して遅延キューを実装する方法 SpringBoot が Redisson を統合して遅延キューを実装する方法 May 30, 2023 pm 02:40 PM

SpringBoot が Redisson を統合して遅延キューを実装する方法

SpringBootとSpringMVCの比較と差異分析 SpringBootとSpringMVCの比較と差異分析 Dec 29, 2023 am 11:02 AM

SpringBootとSpringMVCの比較と差異分析

Springbootがjarパッケージにファイルを読み込んだ後にファイルにアクセスできない問題を解決する方法 Springbootがjarパッケージにファイルを読み込んだ後にファイルにアクセスできない問題を解決する方法 Jun 03, 2023 pm 04:38 PM

Springbootがjarパッケージにファイルを読み込んだ後にファイルにアクセスできない問題を解決する方法

SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法 SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法 Jun 03, 2023 am 11:32 AM

SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法

Springbootでapplication.ymlの値を取得する方法 Springbootでapplication.ymlの値を取得する方法 Jun 03, 2023 pm 06:43 PM

Springbootでapplication.ymlの値を取得する方法

SQL ステートメントを使用せずに Springboot+Mybatis-plus を実装して複数のテーブルを追加する方法 SQL ステートメントを使用せずに Springboot+Mybatis-plus を実装して複数のテーブルを追加する方法 Jun 02, 2023 am 11:07 AM

SQL ステートメントを使用せずに Springboot+Mybatis-plus を実装して複数のテーブルを追加する方法

See all articles