特殊說明:第一章只包含了 初始化上下文,初始化監聽器列表,發佈springboot啟動事件 相關內容 其中一部分代碼 /** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext ...
特殊說明:第一章只包含了 初始化上下文,初始化監聽器列表,發佈springboot啟動事件 相關內容
其中一部分代碼
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
}
1、初始化一個計時器,並開始計時
StopWatch stopWatch = new StopWatch();
stopWatch.start();
其實是用來統計應用啟動耗時的。
實現原理為記錄下開始時間和結束時間,相減即可。
2、初始化啟動上下文
private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
new一個預設的上下文
3、設置該應用程式,即使沒有檢測到顯示器,也允許其啟動
configureHeadlessProperty();
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
設置了一個名為java.awt.headless的系統屬性。
為true時,即使沒有顯示器,也可以啟動。
例如linux伺服器。
4、獲取SpringApplicationRunListener的實現類
SpringApplicationRunListeners listeners = getRunListeners(args);
進入getRunListeners方法
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);
}
①、獲取了一個class數組types
其中的元素分別為:SpringApplication和String數組的class對象。在後續反射初始化對象時,types用於獲取到目標的構造方法。
②、獲取SpringApplicationRunListener實例對象
其中,調用了getSpringFactoriesInstances方法。該方法的目的為:獲取SpringApplicationRunListener介面的所有實現類對象。
在後續的啟動過程中,交由listeners發佈的事件,實際上是遍歷其內部管理的SpringApplicationRunListener對象列表進行發佈的。
需要註意的是,通過getSpringFactoriesInstances方法獲取到的SpringApplicationRunListener類型的對象有且僅有一個:EventPublishingRunListener實例對象。
③、通過獲取到的SpringApplicationRunListener實例,創建一個SpringApplicationRunListeners對象並返回。
第一和第三步比較簡單。
讓我們關註下第二步,getSpringFactoriesInstances方法:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
首先通過getClassLoader方法,獲取到預設的類載入器,
然後通過SpringFactoriesLoader.loadFactoryNames(type, classLoader),獲取SpringApplicationRunListener所有的實現類名稱,
最後創建SpringApplicationRunListener介面的所有實現類對象,排序並返回。