打開SampleSimpleApplication.java
,我們可以看到
public static void main(String[] args) {
//SpringBoot啟動函數(shù)
SpringApplication.run(SampleSimpleApplication.class, args);
}
跟蹤進(jìn)去,可看到
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
其中return new SpringApplication(primarySources).run(args);
為核心方法,創(chuàng)建SpringApplication實例并執(zhí)行run()方法,接下來我們對這句話進(jìn)行分析.
1. 創(chuàng)建SpringApplication
實例
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//resourceLoader賦值給this.resourceLoader
this.resourceLoader = resourceLoader;
//斷言
Assert.notNull(primarySources, "PrimarySources must not be null");
//將primarySources存入LinkedHashSet對象并賦值給this.primarySources
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//推斷當(dāng)前應(yīng)用類型
this.webApplicationType = deduceWebApplicationType();
//初始化Initializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//初始化Listener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推斷主類
this.mainApplicationClass = deduceMainApplicationClass();
}
2. 執(zhí)行run()
完成SpringBoot
啟動
public ConfigurableApplicationContext run(String... args) {
//創(chuàng)建StopWatch對象,用來記錄程序啟動耗時
StopWatch stopWatch = new StopWatch();
//啟動
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//根據(jù)args獲取所有SpringApplicationRunListeners監(jiān)聽器
SpringApplicationRunListeners listeners = getRunListeners(args);
//啟動監(jiān)聽器,首次啟動run方法時立即調(diào)用
listeners.starting();
try {
//創(chuàng)建ApplicationArguments對象,并將args封裝至對象實例
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//準(zhǔn)備環(huán)境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//配置需要忽略的bean
configureIgnoreBeanInfo(environment);
//打印banner
Banner printedBanner = printBanner(environment);
//創(chuàng)建應(yīng)用上下文對象
context = createApplicationContext();
//獲取異常報告對象
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//準(zhǔn)備上下文環(huán)境
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新上下文
refreshContext(context);
//刷新上下文后續(xù)處理
afterRefresh(context, applicationArguments);
//關(guān)閉stopWatch
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//執(zhí)行監(jiān)聽器started方法
listeners.started(context);
callRunners(context, applicationArguments);
} catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
//在run方法完成之前立即調(diào)用井厌,刷新應(yīng)用程序上下文并且所有的CommandLineRunners和ApplicationRunners已經(jīng)被調(diào)用
listeners.running(context);
} catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
至此,我們已經(jīng)可以大概了解到SpringBoot的啟動流程,因為啟動過程中的一些方法比較復(fù)雜,所以我們接下來會分篇幅介紹其中一些核心的方法...