1. 程式人生 > >Spring Boot2.0深入理解SpringApplication第一章

Spring Boot2.0深入理解SpringApplication第一章

在上一篇中已經大致描述了Spring Boot的啟動流程,這篇將根據原始碼詳細講解SpringApplication類中的各種實現原理。通過run方法咱們首先會通過建構函式新建一個SpringApplication物件。咱們看下面程式碼看它具體做了什麼。

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
                //初始化資源載入器
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
                //初始化添加了@SpringBootApplication註解的class
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
                //應用型別
		this.webApplicationType = deduceWebApplicationType();
                //初始化ApplicationContextInitilizer,其中的原理是通過SpringFactoriesLoader來實現的
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
                //初始化監聽Application Listeners(2.0有好幾個listener我沒具體看過都是幹嘛的所以不瞎寫)
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
                //判斷主類,主要作用是日誌列印
		this.mainApplicationClass = deduceMainApplicationClass();
	}

接下來會呼叫初始化好的SpringApplication的run方法。

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
		configureHeadlessProperty();//無關緊要,可以忽略
                //Run Listeners 用於該函式中整個過程事件觸發的監聽EventPublishingRunListener用來呼叫構造器中初始化的幾個listener
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			analyzers = new FailureAnalyzers(context);
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			listeners.finished(context, null);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}

其中下面兩行程式碼

SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();

getRunlisteners方法也同樣是通過SpringFactoriesLoader去獲取spring.factories裡面配置好的EventPublishingRunListener,該累的初始化的建構函式會傳入SpringApplication,並將application中listener儲存到retrievalMutex當中也可以叫defaultRetriever

之後呼叫該listerner中的starting方法程式碼如下

public void starting() {
		this.initialMulticaster.multicastEvent(
				new ApplicationStartingEvent(this.application, this.args));
	}

通過新建的ApplicationStartingEvent去defaultRetriever中獲取相對應event事件的listener執行對應的evet響應方法,並且會將defaultRetriever放入retrieverCache當中下次則可以直接通過evenType以及sourceType組成的key直接獲取listener。到這SpringApplication的新建以及載入listener並執行listener啟動都已經完成。到這咱們已經完成了第一章中的開始以及收集資訊以及註冊回撥介面的階段。下一章將細說建立並準備Environment。

加油!