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啟動的程序已經構造完成,接下來下一篇我們來探討自動化配置是如何實現。