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