一.總結
springboot的啓動流程分下面幾步走:
1.初始化
2.獲取監聽器並啓動監聽器
3.構造容器環境
4.創建容器
5.實例化SpringBootExceptionReporter.class,用來支持報告關於啓動的錯誤
6.準備容器
7.刷新容器
8.刷新容器後置處理
public ConfigurableApplicationContext run(String... args) {
//時間監控
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//java.awt.headless是J2SE的一種模式用於在缺少顯示屏、鍵盤或者鼠標時的系統配置,很多監控工具如jconsole 需要將該值設置爲true,系統變量默認爲true
configureHeadlessProperty();
//獲取spring.factories中的監聽器變量,args爲指定的參數數組,默認爲當前類SpringApplication
//第一步:獲取並啓動監聽器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//第二步:構造容器環境
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//設置需要忽略的bean
configureIgnoreBeanInfo(environment);
//打印banner
Banner printedBanner = printBanner(environment);
//第三步:創建容器
context = createApplicationContext();
//第四步:實例化SpringBootExceptionReporter.class,用來支持報告關於啓動的錯誤
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//第五步:準備容器
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//第六步:刷新容器
refreshContext(context);
//第七步:刷新容器後的擴展接口
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
再來看每一步都做了那些事情:
1.初始化的過程
A.根據加載器中是否包含了某些特定的類來判斷容器類型,在創建容器和容器環境的時候就會被用到。
B.初始化監聽器,利用SpringFactoriesLoader讀取依賴jar下面的所有META-INF/spring.factories文件,獲取SpringApplicationRunListener對應的監聽器全限定名稱,並利用反射初始化。
C.初始化ApplicationContextInitializer對應的Initializer對象。
D.找到main方法所在的類,尋找啓動類
2.獲取監聽器並啓動監聽器
A.獲取META-INF/spring.factories文件中SpringApplicationRunListener對應的所有監聽器,初始化它們或得一個監聽器集合,將這個集合負值給SpringApplicationRunListeners,SpringApplicationRunListeners相當於是一個監聽器的廣播器,要發佈什麼事件都是先由SpringApplicationRunListeners來發布,然後再遍歷所有的監聽器發佈事件。
B.監聽器開始監聽,這裏會創建一個線程池,通過異步的方式來發送事件。
3.構造容器環境
A.根據容器類型來創建不同容器環境對象。
B.加載系統變量和環境變量。
C.監聽器發佈環境準備事件,這個裏面有一個很重要的監聽器ConfigFileApplicationListener,來加載項目的配置文件。
4.創建容器
A.根據初始化時獲取到的容器類型來獲取對應的容器。當容器類型是SERVLET的時候,獲取到的是AnnotationConfigServletWebServerApplicationContext容器
5.實例化SpringBootExceptionReporter.class,用來支持報告關於啓動的錯誤,在try ,cachez中,啓動報錯的時候,異常會被cach捕獲,所以SpringBootExceptionReporter在cache中起作用的。
6.準備容器
A.設置容器環境,將創建好的容器環境賦值給容器
B.執行容器中的ApplicationContextInitializer
C.向各監聽器發送容器準備好了的事件
D.向容器中註冊容器啓動參數
E.將啓動類註冊到容器中
F.發佈容器已加載事件
7.刷新容器
A.刷新上下文環境,初始化上下文環境,對系統的環境變量或者系統屬性進行準備和校驗
B.初始化BeanFactory,解析XML,和填充準備BeanFactory
C.實例化所有剩餘的(non-lazy-init) 單例Bean.
這篇文章比較詳細的刷新容器所做的事情,但是排版比較差,以後有時間整理一下
https://bbs.csdn.net/topics/392397556?page=1#post-409544506
ps:要開始準備找工作了,北京的天氣也越來越冷。