Heim  >  Artikel  >  Java  >  So implementieren Sie den SpringBoot-Listener-Modus

So implementieren Sie den SpringBoot-Listener-Modus

WBOY
WBOYnach vorne
2023-05-20 19:07:191001Durchsuche

Nehmen wir zur Veranschaulichung das Anwendungsstartereignis: ApplicationStartingEvent als Beispiel:

Nehmen Sie die SpringApplication.run-Methode der Startup-Klasse als Einstiegspunkt und befolgen Sie anschließend die beiden Methoden derselben Name in SpringApplication, wir werden sehen, dass die Methode relativ lang ist. Hier poste ich nur die wichtigsten Teile, die eng mit dem Listener zusammenhängen:

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

Der Inhalt der Methode lautet wie folgt:

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

Die Listener wurden hier in die getRunListeners-Methode geladen. Das Ladeprinzip ähnelt dem Systeminitialisierer SpringBoots eingehende Analyse des Initialisierers

Die Logik der Startmethode ist sehr einfach. Rufen Sie einfach die Startmethode von SpringApplicationRunListener auf. Lassen Sie uns diese Startmethode weiter analysieren:

Wir geben die Startmethode der EventPublishingRunListener-Klasse (Implementierungsklasse von SpringApplicationRunListener) ein:

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

Hier wird ein Broadcaster verwendet, um ein neues ApplicationStartingEvent zu übertragen Ereignis.

Wir folgen dieser MulticastEvent-Methode:

	@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

Schauen Sie sich weiterhin die gleichnamige MulticastEvent-Methode an:

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

Der ResolvableType hier umschließt die Ereignis Wir achten nicht darauf; da wir keinen Thread-Pool erstellt haben, ist der Executor leer. Wir konzentrieren uns auf zwei Teile:

Holen Sie sich alle Anwendungs-Listener, die dieses Ereignis abhören

2, invokeListener --> Aktivieren Sie den Listener; Bei der Methode getApplicationListeners (in der Klasse AbstractApplicationEventMulticaster) lautet der Code wie folgt:

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

Das Ereignis im Eingabeparameter ist ApplicationStartingEvent und der Quelltyp ist die Klasse org.springframework.boot.SpringApplication. Ich stelle mir den Typ ListenerRetriever als einen Container vor, der Listener speichert.

Es ist zu erkennen, dass das Programm zunächst im Cache nach einem Retriever vom Typ ListenerRetriever sucht. Wenn dieser nicht gefunden wird, sperrt es ihn und sucht erneut im Cache. Da sich hier kein Inhalt in unserem Cache befindet, wird er nicht zurückgegeben.

Verwenden Sie dann die Methode „retrieApplicationListeners“, um die Listener zu durchlaufen. Die Methode „retrieApplicationListeners“ ist relativ lang. Diese Methode wird verwendet, um zu bestimmen, ob dieser Listener auf das Ereignis achtet Nein, der Zweck des Proxys besteht darin, durch generisches Parsen schließlich die Ereignisse zu erhalten, an denen der Zuhörer interessiert ist.

Wenn festgestellt wird, dass der Zuhörer an der Veranstaltung interessiert ist, wird der Zuhörer zur Zuhörerliste hinzugefügt.

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

Wenn alle Listener für ein Ereignis erfasst sind, gibt die Methode multicastEvent (SimpleApplicationEventMulticaster-Klasse) das Ereignis weiter. Rufen Sie also die allgemeine Triggerschnittstellenmethode des Listeners auf: listener.onApplicationEvent(event); Auf diese Weise wird die Weitergabe dieses Ereignisses abgeschlossen.

Das obige ist der detaillierte Inhalt vonSo implementieren Sie den SpringBoot-Listener-Modus. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen