springboot的啓動流程

一.總結
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:要開始準備找工作了,北京的天氣也越來越冷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章