Spring Boot的執行流程如下圖所示:(圖片來源於網絡)
上圖為SpringBoot啟動結構圖,我們發現啟動流程主要分為三個部分,第一部分進行SpringApplication的初始化模塊,配置一些基本的環境變量、資源、構造器、監聽器,第二部分實現了應用具體的啟動方案,包括啟動流程的監聽模塊、加載配置環境模塊、及核心的創建上下文環境模塊,第三部分是自動化配置模塊,該模塊作為springboot自動配置核心,在后面的分析中會詳細討論。在下面的啟動程序中我們會串聯起結構中的主要功能。下面我們將從入門案例分析Spring Boot相關的原理。
@RestController
@SpringBootApplication
public class DemoApplication
{
@RequestMapping("/")
String index(){
return "Hello World!";
}
public static void main(String[] args)
{
SpringApplication.run(DemoApplication.class, args);
}
}
首先,springboot的啟動類必須滿足以下兩個條件:
l 該類必須在項目的根目錄或者父包中;
l 該類必須有@SpringBootApplication注釋,這個注釋說明了該類為springboot程序的啟動類,是整個程序的入口;
SpringBoot程序啟動時,啟動類的main方法是程序的入口,執行
SpringApplication.run(DemoApplication.class, args);
該方法返回一個ConfigurableApplicationContext對象,使用注解的時候返回的具體類型是AnnotationConfigApplicationContext或AnnotationConfigEmbeddedWebApplicationContext,當支持web的時候是第二個。
當程序開始啟動時,在啟動類中調用SpringApplication的靜態run方法,此時會執行以下操作:
1、首先新建一個SpringApplication對象;
2、然后執行對象的run()方法;
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();//新建一個StopWatch,並啟動用於監測程序運行時間
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();//獲取SpringApplicationRunListeners對象,並啟動該監聽器
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 根據啟動時傳入的參數args,新建ApplicationArguments對象
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); // 新建ConfigurableEnvironment對象,具體類型為StandardServletEnvironment
this.configureIgnoreBeanInfo(environment);// 在其創建過程中將會加載springboot的配置文件application.properties,同時將其綁定的SpringApplication程序中
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();//創建ConfigurableApplicationContext對象context
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);// 執行context的刷新操作
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
3、對配置的啟動類所在包及子包中的類進行掃描,對於有spring相關注解的類,通過反射為其創建代理對象,並交由spring容器管理。
回顧整體流程,Springboot的啟動,主要創建了配置環境(environment)、事件監聽(listeners)、應用上下文(applicationContext),並基於以上條件,在容器中開始實例化我們需要的Bean,至此,通過SpringBoot啟動的程序已經構造完成,接下來下一篇我們來探討自動化配置是如何實現。
