1. 程式人生 > 實用技巧 >SpringBoot啟動分析2:SpringApplicationRunListeners初始化

SpringBoot啟動分析2:SpringApplicationRunListeners初始化

當SpringApplication初始化完畢後,就開始呼叫實際的run方法執行其他初始了:

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

需要注意的是這裡的監聽器和SpringApplication中的監聽器不一樣,前者是SpringApplicationRunListeners型別而後者是ApplicationListener型別。
點選getRunListeners方法進入檢視對應的原始碼:

private SpringApplicationRunListeners getRunListeners(String[] args) {
	Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
	return new SpringApplicationRunListeners(logger,
			getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

可以看出依然是呼叫通用的方法getSpringFactoriesInstances來獲取配置上的資訊,需要注意的是除了型別引數(根據實際型別讀取配置上的實現),還包含已經初始化好的SpringApplication和String類。
EventPublishingRunListener是SpringApplicationRunListeners介面的實現類,這裡讀取出來的配置就是該類,該類用於釋出SpringApplicationEvent型別的事件。
當getSpringFactoriesInstances方法讀取到EventPublishingRunListener資訊後需要呼叫createSpringFactoriesInstances方法將其例項化,在例項化過程中會涉及以下初始化工作:

public EventPublishingRunListener(SpringApplication application, String[] args) {
	this.application = application;
	this.args = args;
	this.initialMulticaster = new SimpleApplicationEventMulticaster();
	for (ApplicationListener<?> listener : application.getListeners()) {
		this.initialMulticaster.addApplicationListener(listener);
	}
}

可以看出初始化SpringApplication時所例項化的所有ApplicationListener型別的監聽器都加入到該廣播中,為了後續使用SpringApplicationRunListeners啟動這些監聽器做了初始化。
當SpringApplicationRunListeners啟動時,通過EventPublishingRunListener呼叫實際的啟動方法:

這時的啟動邏輯就全權交由給EventPublishingRunListener來處理了:

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
	......
	@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}
	......
}	

每個Listener都會間接或直接實現ApplicationListener,所以都需要重寫onApplicationEvent方法,而EventPublishingRunListener就是通過遍歷的方式獲取每一個從spring.factories檔案中讀取並例項化的監聽器,並呼叫這些監聽器的onApplicationEvent方法:

public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
	ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
	Executor executor = this.getTaskExecutor();
	// 獲取到所有監聽器
	Iterator var5 = this.getApplicationListeners(event, type).iterator();
	// 遍歷監聽器並呼叫每個監聽器的onApplicationEvent方法
	while(var5.hasNext()) {
		ApplicationListener<?> listener = (ApplicationListener)var5.next();
		if (executor != null) {
			executor.execute(() -> {
				this.invokeListener(listener, event);
			});
		} else {
			this.invokeListener(listener, event);
		}
	}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
	ErrorHandler errorHandler = this.getErrorHandler();
	if (errorHandler != null) {
		try {
			this.doInvokeListener(listener, event);
		} catch (Throwable var5) {
			errorHandler.handleError(var5);
		}
	} else {
		this.doInvokeListener(listener, event);
	}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
	try {
		// 監聽器例項呼叫本身的onApplicationEvent方法
		listener.onApplicationEvent(event);
	} catch (ClassCastException var6) {
		String msg = var6.getMessage();
		if (msg != null && !this.matchesClassCastMessage(msg, event.getClass())) {
			throw var6;
		}
		Log logger = LogFactory.getLog(this.getClass());
		if (logger.isTraceEnabled()) {
			logger.trace("Non-matching event type for listener: " + listener, var6);
		}
	}
}

這裡不再描述每個監聽器實際的onApplicationEvent方法執行流程,等後續有涉及說明。
備註:對於自定義監聽器,在通過applicationContext.publishEvent(event)釋出之後,其中的邏輯也是走的上方這一套:

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
	Assert.notNull(event, "Event must not be null");
	Object applicationEvent;
	if (event instanceof ApplicationEvent) {
		applicationEvent = (ApplicationEvent)event;
	} else {
		applicationEvent = new PayloadApplicationEvent(this, event);
		if (eventType == null) {
			eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
		}
	}
	if (this.earlyApplicationEvents != null) {
		this.earlyApplicationEvents.add(applicationEvent);
	} else {
		// 實際也是獲取ApplicationEventMulticaster的實現類SimpleApplicationEventMulticaster再通過multicastEvent方法廣播出去。
		this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
	}
	if (this.parent != null) {
	        if (this.parent instanceof AbstractApplicationContext) {
			((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
		} else {
			this.parent.publishEvent(event);
		}
	}
}