前言
實習的第一個項目是利用springboot完成一個需求,在項目搭建的過程中真正感受到springboot的強大,springboot的起步依賴以及自動配置特性簡直不要太爽,在項目搭建的過程中解放了我們的小手。而springboot的啓動也非常簡單,只需要啓動springboot的啓動類,springboot會幫助我們準備所有的環境,包括server,監聽器,裝配spring的上下文等等,springboot的啓動類如此強大我們沒有理由不去深究一下。
目錄
啓動類
@SpringBootApplication
public class SpringTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringTestApplication.class, args);
}
}
SpringTestApplication類執行main方法,main方法調用SpringApplication的run方法。
run方法幹了兩件事:
- 創建SpringApplication對象
- 利用創建好的SpringApplication對象調用run方法
創建SpringApplication對象
在執行SpringApplication的run方法時首先會創建一個SpringApplication類的對象,利用構造方法創建SpringApplication對象時會調用initialize方法。
SpringApplication.run()方法的基本調用流程:
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
}
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
public SpringApplication(Object... sources) {
initialize(sources);
}
initialize方法:
private void initialize(Object[] sources) {
// 在sources不爲空時,保存配置類
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
// 判斷是否爲web應用
this.webEnvironment = deduceWebEnvironment();
// 獲取並保存容器初始化類,通常在web應用容器初始化使用
// 利用loadFactoryNames方法從路徑MEAT-INF/spring.factories中找到所有的ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
// 獲取並保存監聽器
// 利用loadFactoryNames方法從路徑MEAT-INF/spring.factories中找到所有的ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 從堆棧信息獲取包含main方法的主配置類
this.mainApplicationClass = deduceMainApplicationClass();
}
調用run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
// 配置屬性
configureHeadlessProperty();
// 獲取監聽器
// 利用loadFactoryNames方法從路徑MEAT-INF/spring.factories中找到所有的SpringApplicationRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 啓動監聽
// 調用每個SpringApplicationRunListener的starting方法
listeners.starting();
try {
// 將參數封裝到ApplicationArguments對象中
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 準備環境
// 觸發監聽事件——調用每個SpringApplicationRunListener的environmentPrepared方法
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
// 從環境中取出Banner並打印
Banner printedBanner = printBanner(environment);
// 依據是否爲web環境創建web容器或者普通的IOC容器
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
// 準備上下文
// 1.將environment保存到容器中
// 2.觸發監聽事件——調用每個SpringApplicationRunListeners的contextPrepared方法
// 3.調用ConfigurableListableBeanFactory的registerSingleton方法向容器中注入applicationArguments與printedBanner
// 4.觸發監聽事件——調用每個SpringApplicationRunListeners的contextLoaded方法
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 刷新容器,完成組件的掃描,創建,加載等
refreshContext(context);
afterRefresh(context, applicationArguments);
// 觸發監聽事件——調用每個SpringApplicationRunListener的finished方法
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);
}
}
總結
SpringApplication.run一共做了兩件事
- 創建SpringApplication對象;在對象初始化時保存事件監聽器,容器初始化類以及判斷是否爲web應用,保存包含main方法的主配置類。
- 調用run方法;準備spring的上下文,完成容器的初始化,創建,加載等。會在不同的時機觸發監聽器的不同事件。
參考文獻: