此章節主要對springboot啟動程序中,發生的【初始化啟動背景關系】、【初始化監聽器串列】、【發布springboot開始啟動事件】進行原始碼決議,對應的代碼如圖1所示:
圖1:
// 首先初始化一個計時器,并開始計時
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 初始化啟動背景關系
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 設定系統引數:java.awt.headless(在系統可能缺少顯示設備、鍵盤或滑鼠這些外設的情況下可以使用該模式,例如Linux服務器)
configureHeadlessProperty();
// 初始化監聽器串列
SpringApplicationRunListeners listeners = getRunListeners(args);
// 發布springboot開始啟動事件
listeners.starting(bootstrapContext, this.mainApplicationClass);
初始化啟動背景關系
圖2:
private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext));
return bootstrapContext;
}
點擊進入【createBootstrapContext()】方法,可以看到首先獲取了一個DefaultBootstrapContext類實體 -> bootstrapContext,然后遍歷this.bootstrappers對bootstrapContext進行初始化,由于this.bootstrappers中無任何元素(見springboot啟動原始碼決議(一):SpringApplication初始化),故對bootstrapContext未執行任何操作,最后將bootstrapContext回傳,
設定系統引數:java.awt.headless
圖3:
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
在系統可能缺少顯示設備、鍵盤或滑鼠這些外設的情況下可以使用該模式,例如Linux服務器
初始化監聽器串列
圖4:
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
在【getRunListeners】方法中,一共進行了3步操作:
1、獲取了一個class陣列types
其中的元素分別為:SpringApplication和String陣列的class物件,types主要用于在后序反射初始化物件時,獲取到目標的構造方法,
2、獲取SpringApplicationRunListener實體物件,
【getSpringFactoriesInstances】方法的目的為:獲取并維護SpringApplicationRunListener介面的子類物件串列,在后續的啟動程序中,交由listeners發布的事件,實際上是遍歷其內部管理的SpringApplicationRunListener物件串列進行發布的,
最終通過getSpringFactoriesInstances獲取到的SpringApplicationRunListener型別的物件有且僅有一個:EventPublishingRunListener實體物件,
(getSpringFactoriesInstances決議見:springboot啟動原始碼決議(一):SpringApplication初始化:getSpringFactoriesInstances)
3、通過獲取到的SpringApplicationRunListener實體,創建一個SpringApplicationRunListeners物件并回傳,
發布springboot開始啟動事件
圖5:
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction, Consumer<StartupStep> stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}
初始化啟動背景關系和監聽器后,通過呼叫監聽器中的starting方法發布【springboot開始啟動】事件,在starting方法中,實際通過呼叫doWithListeners方法對事件進行發布,
決議doWithListeners方法:
1、初始化一個StartupStep實體,并命名為"spring.boot.application.starting",其作用為:追蹤“執行時間”或其他指標,
2、對內部維護的監聽器串列進行遍歷,執行傳入的listenerAction,故此處是用EventPublishingRunListener實體物件執行starting(bootstrapContext)方法,
如圖6所示,實體化EventPublishingRunListener物件時,在它的構造方法中對成員變數進行了一些初始化操作,初始化initialMulticaster物件時,向其加入了application中維護的9個監聽器物件(application監聽器的由來詳見:springboot啟動原始碼決議(一):SpringApplication初始化),它們分別為:EnvironmentPostProcessorApplicationListener、AnsiOutputApplicationListener、LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、ParentContextCloserApplicationListener、ClearCachesApplicationListener、FileEncodingApplicationListener、LiquibaseServiceLocatorApplicationListener
呼叫EventPublishingRunListener物件的starting方法,實際上是呼叫了其成員變數initialMulticaster的multicastEvent(ApplicationEvent event)方法,
圖6:
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);
}
}
public void starting(ConfigurableBootstrapContext bootstrapContext) {
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
進入initialMulticaster.multicastEvent(ApplicationEvent event)進行查看,如圖7所示,
在 multicastEvent(final ApplicationEvent event, ResolvableType eventType)方法中:
1、呼叫 getApplicationListeners(event, type)能夠在initialMulticaster維護的監聽器串列中找到匹配該事件的監聽器串列
此處符合ApplicationStartingEvent事件的監聽器有:LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、LiquibaseServiceLocatorApplicationListener
2、對符合要求的監聽器進行遍歷,執行invokeListener(listener, event)方法
由于在initialMulticaster中,執行緒池為null,故直接執行invokeListener(listener, event)方法,如圖8所示,invokeListener(listener, event)方法實際是呼叫了listener.onApplicationEvent(event)方法,
當事件為ApplicationStartingEvent時,LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、LiquibaseServiceLocatorApplicationListener的onApplicationEvent(event)如圖9所示,LoggingApplicationListener初始化了loggingSystem,其它三個listener未執行任何操作
圖7:
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
/**
* 決議事件型別
*/
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
/**
* 批量消費事件
*/
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);
}
}
}
圖8:
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
圖9:
/**
* 當listener為LoggingApplicationListener時
*/
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
else if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
}
else if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
}
else if (event instanceof ContextClosedEvent
&& ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {
onContextClosedEvent();
}
else if (event instanceof ApplicationFailedEvent) {
onApplicationFailedEvent();
}
}
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
// 初始化loggingSystem
this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
this.loggingSystem.beforeInitialize();
}
// ---------------------------------------------------------------
/**
* 當listener為BackgroundPreinitializer時,由于未識別到ApplicationStartingEvent事件,故不執行任何操作
*/
public void onApplicationEvent(SpringApplicationEvent event) {
if (!ENABLED) {
return;
}
if (event instanceof ApplicationEnvironmentPreparedEvent
&& preinitializationStarted.compareAndSet(false, true)) {
performPreinitialization();
}
if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent)
&& preinitializationStarted.get()) {
try {
preinitializationComplete.await();
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
// ---------------------------------------------------------------
/**
* 當listener為DelegatingApplicationListener時,由于未識別到ApplicationStartingEvent事件,故不執行任何操作
*/
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
if (delegates.isEmpty()) {
return;
}
this.multicaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<ApplicationEvent> listener : delegates) {
this.multicaster.addApplicationListener(listener);
}
}
if (this.multicaster != null) {
this.multicaster.multicastEvent(event);
}
}
// ---------------------------------------------------------------
/**
* 當listener為LiquibaseServiceLocatorApplicationListener時,由于LIQUIBASE_PRESENT為false,故不執行任何操作
*/
public void onApplicationEvent(ApplicationStartingEvent event) {
if (LIQUIBASE_PRESENT) {
new LiquibasePresent().replaceServiceLocator();
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/260401.html
標籤:java
