以前博文已經講過,@SpringBootApplication繼承了@EnableAutoConfiguration,該註解導入了AutoConfigurationImport Selector,這個類主要是掃描spring-boot-autoconfigure下面的META-INF\spring.factories中的EnableAutoConfiguration對應的全類名,其中XXXAutoConfiguration都是一個個自動配置類。html
自動裝配原理具體參考:Spring Boot系列(二):Spring Boot自動裝配原理解析
web
① EmbeddedWebServerFactoryCustomizerAutoConfiguration內嵌的Web容器工廠定製器自動裝配類,裝配了TomcatWebServerFactoryCustomizer組件spring
Tomcat工廠定製器TomcatWebServerFactoryCustomizer用來設置容器的屬性,把ServerProperties中的屬性設置到Tomcat容器的工廠中。服務器
ServerProperties服務的屬性類:app
② ServletWebServerFactoryAutoConfiguration,ServletWeb工廠自動裝配類,裝配了以下四個組件less
① new SpringApplication(primarySources),建立了一個SpringApplicationspring-boot
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); //設置主配置類 咱們本身寫的Spring Boot的啓動類 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //設置web應用的類型 this.webApplicationType = WebApplicationType.deduceFromClasspath(); //設置容器初始化器(ApplicationContextInitializer類型的) setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); //把監聽器設置到SpringApplication中[ApplicationListener] setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //設置主配置類 this.mainApplicationClass = deduceMainApplicationClass(); }
② SpringApplication的run方法:this
主要流程:spa
第一:建立容器對象命令行
第二:去META-INFO/spring.factories中獲取SpringApplicationRunListener監聽器(事件發佈監聽器)
第三:發佈容器starting事件(經過spring的事件多播器)
第四:封裝命令行參數
第五:準備容器環境
第六:打印Springboot的圖標
第七:根據webApplicationType來建立容器
第八:準備容器上下文
第九:發佈容器啓動事件
第十:發佈容器運行事件
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); //容器對象 ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); //去META-INFO/spring.factories中獲取SpringApplicationRunListener監聽器(事件發佈監聽器) SpringApplicationRunListeners listeners = getRunListeners(args); //發佈容器starting事件(經過spring的事件多播器) listeners.starting(); try { //封裝命令行參數 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); /** * 準備容器環境 * 1: 獲取或者建立環境 * 2:把命令行參數設置到環境中 * 3:經過監聽器發佈環境準備事件 */ ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); //打印Springboot的圖標 Banner printedBanner = printBanner(environment); //建立容器根據webApplicationType來建立容器(經過反射建立) context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); /** * 準備上下文 * 1:把環境設置到容器中 * 2: 循環調用ApplicationContextInitializer進行容器初始化工做 * 3: 發佈容器上下文準備完成事件 * 4: 註冊關於Springboot特性的相關單例Bean * 5: 發佈容器上下文加載完畢事件 */ prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); //運行ApplicationRunner和CommandLineRunner afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } //發佈容器啓動事件 listeners.started(context); //運行ApplicationRunner和CommandLineRunner callRunners(context, applicationArguments); } catch (Throwable ex) { //出現異常調用異常分析保護類進行分析 handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { //發佈容器運行事件 listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }
③ org.springframework.boot.SpringApplication#refreshContext
④ org.springframework.boot.SpringApplication#refresh
⑤ org.springframework.context.support.AbstractApplicationContext#refresh
到了AbstractApplicationContext#refresh方法,以前講過Spring IoC源碼解析講過該方法的12大步,這裏就不細說,詳細能夠參考:Spring系列(三):Spring IoC源碼解析,裏面說過有一步就是onRefresh(),這個方法默認是空的,由子類根據自身須要去實現
⑥ org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
該onRefresh方法分2步
第一:super.onRefresh(); 調用父類的onRefresh()
第二:createWebServer();建立Web服務,很重要,很重要,很重要!!!
⑦ createWebServer()方法
第一:ServletContext servletContext = getServletContext(); 獲取Servlet的上下文
第二:ServletWebServerFactory factory = getWebServerFactory();獲取Tomcat的Web服務工廠
第三:this.webServer = factory.getWebServer(getSelfInitializer()); 建立一個Web服務器
⑧ TomcatServletWebServerFactory#getWebServer()方法,主要用於建立一個Tomcat Web容器
到此咱們知道Spring Boot的啓動經過Spring IoC的refresh中的的onRefresh()帶動了Tomcat的啓動,跟咱們以前咱們學Spring Mvc的時候恰好相反,Spring Mvc的是Tomcat的啓動帶動了Spring容器的啓動;
這個方法很熟悉了,Spring IoC的refresh的12大步;