SpringBoot源碼解讀之啓動流程

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // <1>
public class MVCApplication {

    public static void main(String[] args) {
        SpringApplication.run(MVCApplication.class, args); // <2>
    }

}
public static void main(String[] args) throws Exception {
		SpringApplication.run(new Class<?>[0], args);
	}
	
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}
/**
 * 資源加載器
 */
private ResourceLoader resourceLoader;
/**
 * 主要的 Java Config 類的數組
 */
private Set<Class<?>> primarySources;
/**
 * Web 應用類型
 */
private WebApplicationType webApplicationType;

/**
 * ApplicationContextInitializer 數組
 */
private List<ApplicationContextInitializer<?>> initializers;
/**
 * ApplicationListener 數組
 */
private List<ApplicationListener<?>> listeners;

@SuppressWarnings({ "unchecked", "rawtypes" })
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

run方法

public ConfigurableApplicationContext run(String... args) {
		// <1> 創建 StopWatch 對象,並啓動。StopWatch 主要用於簡單統計 run 啓動過程的時長。
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		// <2> 配置 headless 屬性
		configureHeadlessProperty();
		// 獲得 SpringApplicationRunListener 的數組,並啓動監聽
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			// <3> 創建  ApplicationArguments 對象
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			// <4> 加載屬性配置。執行完成後,所有的 environment 的屬性都會加載進來,包括 application.properties 和外部的屬性配置
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			// <5> 打印 Spring Banner
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			// <7> 異常報告器
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			// <8> 主要是調用所有初始化類的 initialize 方法
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			// <9> 初始化 Spring 容器。
			refreshContext(context);
			// <10> 執行 Spring 容器的初始化的後置邏輯。默認實現爲空。
			afterRefresh(context, applicationArguments);
			// <11> 停止 StopWatch 統計時長
			stopWatch.stop();
			// <12> 打印 Spring Boot 啓動的時長日誌。
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			// <13> 通知 SpringApplicationRunListener 的數組,Spring 容器啓動完成。
			listeners.started(context);
			// <14> 調用 ApplicationRunner 或者 CommandLineRunner 的運行方法。
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			// <14.1> 如果發生異常,則進行處理,並拋出 IllegalStateException 異常
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		// <15> 通知 SpringApplicationRunListener 的數組,Spring 容器運行中。
		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			// <15.1> 如果發生異常,則進行處理,並拋出 IllegalStateException 異常
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		// <1> 創建 ConfigurableEnvironment 對象,並進行配置
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		// <2> 通知 SpringApplicationRunListener 的數組,環境變量已經準備完成。
		listeners.environmentPrepared(environment);
		// <3> 綁定 environment 到 SpringApplication 上
		bindToSpringApplication(environment);
		// <4> 如果非自定義 environment ,則根據條件轉換
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		// <5> 如果有 attach 到 environment 上的 MutablePropertySources ,則添加到 environment 的 PropertySource 中。
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

流程圖如下,圖片來源於網絡
在這裏插入圖片描述

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