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;
}
流程圖如下,圖片來源於網絡