new SpringApplication()創建實例
Create a new {@link SpringApplication} instance
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
實例化SpringApplication流程
- 推斷web類型(SERVLET)
- 設置ApplicationContextInitializer
- 利用工廠加載機制實例化ApplicationContextInitializer的子類
- 設置ApplicationListener監聽類
- 推到main方法運行的主類
工廠加載機制SpringFactoriesLoader
介紹
- 框架內部通用工廠加載機制
- 從classpath下多個jar包特定的位置讀取文件並初始化類
- 文件內容必須k-v形式,即properties類型
- key是全限定名(抽象類|接口)、value是實現、多個實現,分割
SpringApplication.getSpringFactoriesInstances(Xxxx.class);
1.實例化EventPublishingRunListener
//工廠加載機制
SpringFactoriesLoader.loadFactoryNames()
加載流程圖
框架啓動方法run()
框架啓動流程
計時器》Headless模式賦值》發送ApplicationStartingEvent》配置環境模塊》打印banner》創建應用上下文對象》初始化失敗分析器》關聯springboot組件與應用上下文對象》發送ApplicationContextInitializedEvent》加載sources到context》發送ApplicationPreparedEvent》刷新上下文》計時器停止計時》發送ApplicationContextStartedEvent》調用框架啓動擴展類==》發送ApplicationReadyEvent
系統初始化器解析ApplicationContextInitializer
調用順序
-
//應用準備階段 prepareContext(); //spring中刷新上下文的核心方法 refreshContext(context); // prepareContext(){ ... applyInitializers(); ... }
加載spring.factories中註冊在
ApplicationContextInitializer
初始化類
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
調用模板類ApplicationContextInitializer.initialize()方法,完成初始化。
實現步驟:
1.實現ApplicationContextInitializer接口
2.spring.factories內填寫接口實現
SpringBoot監聽器解析
監聽器模式介紹
- 事件
- 監聽器
- 廣播器
- 觸發機制
系統監聽器介紹ApplicationListener
-
事件
ApplicationEvent
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-X9sPJo9l-1593612510738)(C:\Users\ACER\AppData\Roaming\Typora\typora-user-images\image-20200629190925223.png)]
-
監聽器
interface ApplicationListener
-
廣播器
interface ApplicationEventMulticaster
監聽器註冊
同上系統初始化註冊,通過SpringFactories.loadFactoryNames()加載配置在spring.factories中的ApplicationListener.class的實現類
監聽事件觸發機制
***以run()中的SpringApplicationRunListener爲例子
-
SpringApplicationRunListeners listeners = getRunListeners(args);
-
listeners.starting(); //SpringApplicationRunListener的集合
- listener.starting(); //開啓入口,實現在EventPublishingRunListener
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
//由事件廣播發布ApplicationStartingEvent事件
//event:事件本身,eventType:shiji
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
//根據事件獲取對應的監聽對象getApplicationListeners()
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
//觸發監聽器
invokeListener(listener, event);
}
}
}
ResolvableType代表事件的類型解析,ApplicationEvent代表事件本身
1.獲取監聽getApplicationListeners(ApplicationEvent event, ResolvableType eventType)
- 緩存中查找監聽 this.retrieverCache.get(cacheKey)
- 檢索出所有的感興趣的監聽 retrieveApplicationListeners(eventType, sourceType, retriever);
1.1監聽檢索retrieveApplicationListeners()
1.1.1加載所有監聽
1.1.2遍歷監聽,篩選出對事件感興趣的監聽supportsEvent(listener, eventType, sourceType);
listener intanceof GenericApplicationListener;不屬於則使用適配器轉換爲GenericApplicationListener類型,最後判斷是否支持事件來判斷是否感興趣,後面的一個判斷一般爲true; (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType))
1.1.3將感興趣的監聽加入到監聽檢索ListenerRetriever中。
1.1.4監聽排序
1.2將監聽加入到索引緩存retrieverCache
2.調用監聽invokeListener()
- 調用ApplicationListener中唯一的監聽調用方法listener.onApplicationEvent(event);
SpringBoot Banner
配置文件配置banner的位置
banner獲取原理
run方法代碼入口: Banner printedBanner = printBanner(environment);
核心類:資源加載ResourceLoader、banner包裝Banner、輸出PrintStream
計時器
run方法代碼入口:
StopWatch stopWatch = new StopWatch();
stopWatch.start();
stopWatch.stop();
啓動加載器
可以在springboot啓動後加載。
run方法代碼入口:callRunners(context, applicationArguments);
方法實現方式
- 添加ApplicationRunner實現至runners中
- 添加CommondLineRunner實現至runners中
- 對runners集合排序
- 遍歷調用實現類的run方法
自定義實現方式
- 繼承實現CommandLineRunner
- 繼承實現ApplicationRunner
面試題