1. 程式人生 > >SpringApplication.run執行流程

SpringApplication.run執行流程

1.這個方法裡面首先建立一個SpringApplication物件例項,然後呼叫這個建立好的SpringApplication的例項方法。在SpringApplication例項初始化的時候,它會提前做幾件事情:

@SuppressWarnings({ "unchecked", "rawtypes" })
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//把sources設定到SpringApplication的sources屬性中
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		this.webApplicationType = deduceWebApplicationType();
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

(1)根據classpath裡面是否存在某個特徵類來決定web應用型別,這個型別會用來建立相應的ApplicationContext

(2)使用SpringFactoriesLoader在應用的classpath中查詢並載入所有可用的ApplicationContextInitializer.

(3)使用SpringFactoriesLoader在應用的classpath中查詢並載入所有可用的ApplicationListener.

(4)推斷並設定main方法的定義類。

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			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;
	}

2. SpringApplication例項初始化完成並且完成設定後,就開始執行run方法的邏輯了,首先遍歷所有通過SpringFactoriesLoader載入的SpringApplicationRunListener,呼叫它們的started方法。

3. 建立並配置當前Spring Boot應用將要使用的Environment

4. 遍歷呼叫所有SpringApplicationRunListener的environmentPrepared()的方法

5. 如果SpringApplication的showBanner屬性被設定為true,則列印banner

6. 根據使用者是否明確設定了applicationContextClass型別以及初始化階段的推斷結果,決定該為當前SpringBoot應用建立什麼型別的ApplicationContext,然後根據條件決定是否新增ShutdownHook,決定是否使用自定義的BeanNameGenerator,決定是否使用自定義的ResourceLoader,最重要的,是將之前準備好的Environment設定給建立好的ApplicationContext使用。

7. ApplicationContext建立好之後,SpringApplication會再次藉助Spring-FactoriesLoader,查詢並載入classpath中所有可用的ApplicatinContext-Initializer,然後遍歷呼叫這些ApplicationContextInitializer的initialize(applicationContext)方法對已經建立好的ApplicationContext進行進一步的處理。

8.遍歷呼叫所有SpringApplicationRunListener的contextPrepared()方法。

9. 最核心的一步,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置載入到已經準備完畢的ApplicationContext。

10. 遍歷呼叫所有SpringApplicationRunListener的contextLoaded()方法。

11.呼叫ApplicationContext的refresh()方法,完成IoC容器可用的最後上道工序。

12. 查詢當前ApplicationContext中是否註冊有CommandLineRunner,如果有,則遍歷執行它們。

13. 正常情況下,遍歷執行SpringApplicationRunListener的方法表示啟動完成(如果整個過程出現異常,會把異常資訊也傳給listener)

最後歡迎大家訪問我的個人網站:1024s​​​​​​​