Spring Boot原理分析

1.Spring Boot 簡介

簡化Spring應用開發的一個框架;

內嵌Servler容器

減少了配置文件

2.微服務

每一個功能元素最終都是一個可獨立替換和獨立升級的軟件單元;

3.打包插件

 <!-- 這個插件,可以將應用打包成一個可執行的jar包;-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

將這個應用打成jar包,直接使用java -jar的命令進行執行;

4.Spring boot父POM文件

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
</parent>

他的父項目是
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-dependencies</artifactId>
  <version>1.5.9.RELEASE</version>
  <relativePath>../../spring-boot-dependencies</relativePath>
</parent>
他來真正管理Spring Boot應用裏面的所有依賴版本;

Spring Boot的版本仲裁中心;

以後我們導入依賴默認是不需要寫版本;(沒有在dependencies裏面管理的依賴自然需要聲明版本號)

5.激活指定profile

1、在配置文件中指定 spring.profiles.active=dev

​ 2、命令行:

​ java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;

​ 可以直接在測試的時候,配置傳入命令行參數

​ 3、虛擬機參數;

​ -Dspring.profiles.active=dev

6.配置文件加載位置

springboot 啓動會掃描以下位置的application.properties或者application.yml文件作爲Spring boot的默認配置文件

–file:./config/

–file:./

–classpath:/config/

–classpath:/

優先級由高到底,高優先級的配置會覆蓋低優先級的配置;

SpringBoot會從這四個位置全部加載主配置文件;互補配置

7.spring boot啓動器

導入web容器正常運行所依賴組件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot將所有的功能場景都抽取出來,做成一個個的starters(啓動器),只需要在項目裏面引入這些starter相關場景的所有依賴都會導入進來。要用什麼功能就導入什麼場景的啓動器

8.spring啓動原理

/**
 *  @SpringBootApplication 來標註一個主程序類,說明這是一個Spring Boot應用
 */
@SpringBootApplication
public class HelloWorldMainApplication {

    public static void main(String[] args) {

        // Spring應用啓動起來
        SpringApplication.run(HelloWorldMainApplication.class,args);
    }
}

@SpringBootApplication: Spring Boot應用標註在某個類上說明這個類是SpringBoot的主配置類,SpringBoot運行這個類的main方法來啓動SpringBoot應用;

6.1 springBootApplication註解信息
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//是個配置類
@Configuration(proxyBeanMethods = false)
public @interface SpringBootConfiguration {}
6.2 @SpringBootConfiguration
  1. @SpringBootConfiguration:Spring Boot的配置類,標註在某個類上,表示這是一個Spring Boot的配置類;
    • @Configuration:配置類上來標註這個註解;是個配置類,代替以前的配置文件,配置類也是容器中的一個組件;@Component
6.3@EnableAutoConfiguration

​ @EnableAutoConfiguration:開啓自動配置功能,以前我們需要配置的東西,Spring Boot幫我們自動配置;告訴SpringBoot開啓自動配置功能;這樣自動配置才能生效;

@AutoConfigurationPackage//自動配置包
@Import(EnableAutoConfigurationImportSelector.class)//給容器中導入一個組件,導入的組件由AutoConfigurationPackages.Registrar.class;
public @interface EnableAutoConfiguration {}
  1. @AutoConfigurationPackage:自動配置包

​ @Import(AutoConfigurationPackages.Registrar.class):給容器中導入一個組件,主配置類(@SpringBootApplication標註的類)的所在包及下面所有子包裏面的所有組件掃描到Spring容器

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)//給容器中導入一個組件,導入的組件由AutoConfigurationPackages.Registrar.class;
public @interface AutoConfigurationPackage {}
	
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
      //主配置類的所在包及下面所有子包裏面的所有組件掃描到Spring容器
			register(registry, new PackageImport(metadata).getPackageName());
		}
	}
  1. @Import(EnableAutoConfigurationImportSelector.class)
    給容器導入EnableAutoConfigurationImportSelector組件,將所有需要導入的組件以全類名的方式返回,這些組件將被添加都容器中 ,**會給容器中導入非常多的自動配置類(xxxAutoConfiguration);就是給容器中導入這個場景需要的所有組件,並配置好這些組件;**有了自動配置類,免去了我們手動編寫配置注入功能組件等的工作;

    @Override
    	public String[] selectImports(AnnotationMetadata annotationMetadata) {
    		if (!isEnabled(annotationMetadata)) {
    			return NO_IMPORTS;
    		}
    		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
    				.loadMetadata(this.beanClassLoader);
    		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
    				annotationMetadata);
    		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    	}
    
    //核心在getAutoConfigurationEntry裏面的
    List<String> configurations =SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
    	getBeanClassLoader());
    //掃描所有jar包從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration**指定的值(上面截圖),將這些值作爲自動配置類導入到容器中
    

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UYCPJtHY-1576169155091)(/Users/laiyanxin/Library/Application Support/typora-user-images/image-20191209230257265.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-p3ncr8O5-1576169155093)(/Users/laiyanxin/Library/Application Support/typora-user-images/image-20191209230646961.png)]

裏面SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);主要是Spring Boot在啓動的時候掃描所有jar包從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的值(上面截圖),將這些值作爲自動配置類導入到容器中,自動配置類就生效,幫我們進行自動配置工作;以前我們需要自己配置的東西,自動配置類都幫我們

  1. 以**HttpEncodingAutoConfiguration(Http編碼自動配置)**爲例解釋自動配置原理;
@Configuration(proxyBeanMethods = false)//表示這個一個配置類,以前編寫的配置文件一樣,也可以給容器添加組件
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {}

9.SpringMVC自動配置原理

9.1Spring MVC auto-configuration

官方文檔解釋

Spring Boot provides auto-configuration for Spring MVC that works well with most applications.

The auto-configuration adds the following features on top of Spring’s defaults:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
    • 自動配置了ViewResolver(視圖解析器:根據方法的返回值得到視圖對象(View),視圖對象決定如何渲染(是轉發還是重定向)
    • ContentNegotiatingViewResolver組合了所有視圖解析器
    • 我們可以自己給容器中添加一個視圖解析器;自動的將其組合進來.會加入ContentNegotiatingViewResolver
  • Support for serving static resources, including support for WebJars (see below).
    支持靜態資源文件webjar
  • Automatic registration of Converter, GenericConverter, Formatter beans.
    • 自動註冊了Converter, GenericConverter, Formatter beans
    • Converter:轉換器,例子:我們接受對象Person,類型轉換用Converter
    • Formatter:格式化器;例子:前端傳2019.12.12通過格式化器轉成Date
    • 自己添加的格式化器轉換器,我們只需要放在容器中即可=
  • Support for HttpMessageConverters (see below).
    • HttpMessageConverter:SpringMVC用來轉換Http請求和響應的;User—Json;
    • HttpMessageConverters 是從容器中確定;獲取所有的HttpMessageConverter;
    • 自己給容器中添加HttpMessageConverter,只需要將自己的組件註冊容器中@Bean,@Component
  • Automatic registration of MessageCodesResolver (see below).
    定義錯誤代碼生成規則
  • Static index.html support. 靜態首頁訪問
  • Custom Favicon support (see below).
  • Automatic use of a ConfigurableWebBindingInitializer bean (see below).
    • 我們可以配置一個ConfigurableWebBindingInitializer來替換默認的
    • 初始化WebDataBinder;請求數據=====JavaBean;

If you want to keep Spring Boot MVC features, and you just want to add additional MVC configuration (interceptors, formatters, view controllers etc.) you can add your own @Configuration class of type WebMvcConfigurerAdapter, but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter or ExceptionHandlerExceptionResolver you can declare a WebMvcRegistrationsAdapter instance providing such components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

9.2、擴展SpringMVC

編寫一個配置類(@Configuration),是WebMvcConfigurerAdapter類型;不能標註@EnableWebMvc
既保留了所有的自動配置,也能用我們擴展的配置;
使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能

//使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //瀏覽器發送 /xx 請求來到 success
        registry.addViewController("/xx").setViewName("success");
    }
}

原理:

  1. WebMvcAutoConfiguration是SpringMVC的自動配置類

  2. 在做其他自動配置時會導入;@Import(EnableWebMvcConfiguration.class)

        @Configuration
    	public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
          private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
    
    	 //從容器中獲取所有的WebMvcConfigurer List<WebMvcConfigurer> configurers
          @Autowired(required = false)
          public void setConfigurers(List<WebMvcConfigurer> configurers) {
              if (!CollectionUtils.isEmpty(configurers)) {
                  this.configurers.addWebMvcConfigurers(configurers);
                	//一個參考實現;將所有的WebMvcConfigurer相關配置都來一起調用;  
                	@Override
                 // public void addViewControllers(ViewControllerRegistry registry) {
                  //    for (WebMvcConfigurer delegate : this.delegates) {
                   //       delegate.addViewControllers(registry);
                   //   }
                  }
              }
    	}
    
  3. 容器中所有的WebMvcConfigurer都會一起起作用;

  4. 我們的配置類也會被調用;

​ 效果:SpringMVC的自動配置和我們的擴展配置都會起作用;

9.3全面接管SpringMVC

SpringBoot對SpringMVC的自動配置不需要了,所有都是我們自己配置;所有的SpringMVC的自動配置都失效了我們需要在配置類中添加@EnableWebMvc即可

//使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能
@EnableWebMvc
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
       // super.addViewControllers(registry);
        //瀏覽器發送 /atguigu 請求來到 success
        registry.addViewController("/atguigu").setViewName("success");
    }
}

原理:爲什麼@EnableWebMvc自動配置就失效了;

  1. @EnableWebMvc的核心

    @Import(DelegatingWebMvcConfiguration.class)
    public @interface EnableWebMvc {
    
  2. @Configuration
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {}
    
  3. 容器中沒有WebMvcConfigurationSupport這個組件的時候,這個自動配置類才生效

    @Configuration
    @ConditionalOnWebApplication
    @ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
    		WebMvcConfigurerAdapter.class })
    //容器中沒有這個組件的時候,這個自動配置類才生效
    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
    @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
    		ValidationAutoConfiguration.class })
    public class WebMvcAutoConfiguration {
    
  4. @EnableWebMvc將WebMvcConfigurationSupport組件導入進來;

  5. 導入的WebMvcConfigurationSupport只是SpringMVC最基本的功能;

10.如何修改SpringBoot的默認配置

  1. SpringBoot在自動配置很多組件的時候,先看容器中有沒有用戶自己配置的(@Bean、@Component)如果有就用用戶配置的,如果沒有,才自動配置;如果有些組件可以有多個(ViewResolver)將用戶配置的和自己默認的組合起來;
  2. 在SpringBoot中會有非常多的xxxConfigurer幫助我們進行擴展配置
  3. 在SpringBoot中會有很多的xxxCustomizer幫助我們進行定製配置

11.嵌入式Servlet容器自動配置原理

EmbeddedServletContainerAutoConfiguration:嵌入式的Servlet容器自動配置

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@Import(BeanPostProcessorsRegistrar.class)
//導入BeanPostProcessorsRegistrar:給容器中導入一些組件
//導入了EmbeddedServletContainerCustomizerBeanPostProcessor:
public class EmbeddedServletContainerAutoConfiguration {
    
    @Configuration
	@ConditionalOnClass({ Servlet.class, Tomcat.class })//判斷當前是否引入了Tomcat依賴;
	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)//判斷當前容器沒有用戶自己定義EmbeddedServletContainerFactory:嵌入式的Servlet容器工廠;作用:創建嵌入式的Servlet容器
	public static class EmbeddedTomcat {

		@Bean
		public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
			return new TomcatEmbeddedServletContainerFactory();
		}

	}
    
  /**
  *判斷當前是否引入了Jetty依賴;
  **/
	@Configuration
	@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
			WebAppContext.class })
	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
	public static class EmbeddedJetty {

		@Bean
		public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
			return new JettyEmbeddedServletContainerFactory();
		}

	}

	/**
	 * 判斷當前是否引入了Undertow依賴
	 */
	@Configuration
	@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
	public static class EmbeddedUndertow {

		@Bean
		public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
			return new UndertowEmbeddedServletContainerFactory();
		}

	}

springboot會根據你導入的依賴來選擇servlet容器

3)、以TomcatEmbeddedServletContainerFactory爲例

@Override
public EmbeddedServletContainer getEmbeddedServletContainer(
      ServletContextInitializer... initializers) {
    //創建一個Tomcat
   Tomcat tomcat = new Tomcat();
    
    //配置Tomcat的基本環節
   File baseDir = (this.baseDirectory != null ? this.baseDirectory
         : createTempDir("tomcat"));
   tomcat.setBaseDir(baseDir.getAbsolutePath());
   Connector connector = new Connector(this.protocol);
   tomcat.getService().addConnector(connector);
   customizeConnector(connector);
   tomcat.setConnector(connector);
   tomcat.getHost().setAutoDeploy(false);
   configureEngine(tomcat.getEngine());
   for (Connector additionalConnector : this.additionalTomcatConnectors) {
      tomcat.getService().addConnector(additionalConnector);
   }
   prepareContext(tomcat.getHost(), initializers);
    
    //將配置好的Tomcat傳入進去,返回一個EmbeddedServletContainer;並且啓動Tomcat服務器
   return getTomcatEmbeddedServletContainer(tomcat);
}

4)、我們對嵌入式容器的配置修改是怎麼生效?

可以通過ServerProperties(也是定製器)配置文件、EmbeddedServletContainerCustomizer 定製器幫我們修改

5)、修改的原理

容器中導入了EmbeddedServletContainerCustomizerBeanPostProcessor

//初始化之前
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
    //如果當前初始化的是一個ConfigurableEmbeddedServletContainer類型的組件
   if (bean instanceof ConfigurableEmbeddedServletContainer) {
       //
      postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
   }
   return bean;
}

private void postProcessBeforeInitialization(
			ConfigurableEmbeddedServletContainer bean) {
    //獲取所有的定製器,調用每一個定製器的customize方法來給Servlet容器進行屬性賦值;
    for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
        customizer.customize(bean);
    }
}

private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
    if (this.customizers == null) {
        // Look up does not include the parent context
        this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
            this.beanFactory
            //從容器中獲取所有這葛類型的組件:EmbeddedServletContainerCustomizer
            //定製Servlet容器,給容器中可以添加一個EmbeddedServletContainerCustomizer類型的組件
            .getBeansOfType(EmbeddedServletContainerCustomizer.class,
                            false, false)
            .values());
        Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
        this.customizers = Collections.unmodifiableList(this.customizers);
    }
    return this.customizers;
}

步驟:

1)、SpringBoot根據導入的依賴情況,給容器中添加相應的EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】

2)、容器中某個組件要創建對象就會通過後置處理器;EmbeddedServletContainerCustomizerBeanPostProcessor;

只要是嵌入式的Servlet容器工廠,後置處理器就工作;

3)、後置處理器,從容器中獲取所有的EmbeddedServletContainerCustomizer,調用定製器的定製方法

12嵌入式的Servlet容器啓動原理

什麼時候創建嵌入式的Servlet容器工廠?什麼時候獲取嵌入式的Servlet容器並啓動Tomcat;

IOC容器啓動創建嵌入式的Servlet容器

源碼:

獲取嵌入式的Servlet容器工廠:

1)、SpringBoot應用啓動運行run方法

2)、refreshContext(context);

​ SpringBoot刷新IOC容器【創建IOC容器對象,並初始化容器,創建容器中的每一個組件】;如果是web應用創建AnnotationConfigEmbeddedWebApplicationContext,否則:AnnotationConfigApplicationContext

3)、refresh(context);刷新剛纔創建好的ioc容器;

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

4)、 onRefresh(); web的ioc容器重寫了onRefresh方法

5)、webioc容器會創建嵌入式的Servlet容器;createEmbeddedServletContainer();

6)、獲取嵌入式的Servlet容器工廠:

EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();

​ 從ioc容器中獲取EmbeddedServletContainerFactory 組件;TomcatEmbeddedServletContainerFactory創建對象,後置處理器一看是這個對象,就獲取所有的定製器來先定製Servlet容器的相關配置;

7)、使用容器工廠獲取嵌入式的Servlet容器:this.embeddedServletContainer = containerFactory .getEmbeddedServletContainer(getSelfInitializer());

8)、嵌入式的Servlet容器創建對象並啓動Servlet容器;

先啓動嵌入式的Servlet容器,再將ioc容器中剩下沒有創建出的對象獲取出來;

13啓動原理

啓動流程

1.創建SpringApplication對象,在該對象初始化時,找到配置的事件監聽器,並保存起來
public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
}

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
		return new SpringApplication(sources).run(args);
	}

public SpringApplication(Object... sources) {
		initialize(sources);
	}


private void initialize(Object[] sources) {
  //保存主配置類
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
  //判斷當前環境是不是Web環境
		this.webEnvironment = deduceWebEnvironment();
  //從類路徑下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然後保存起來
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
  //從類路徑下找到ETA-INF/spring.factories配置的所有ApplicationListener
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  //從多個配置類中找到有main方法的主配置類
		this.mainApplicationClass = deduceMainApplicationClass();
	}
2.運行run方法
public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
  //1.獲取SpringApplicationRunListeners;從類路徑下META-INF/spring.factories
   SpringApplicationRunListeners listeners = getRunListeners(args);
  //2/回調所有的SpringApplicationRunListeners的starting
   listeners.starting();
   try {
     //3.封裝命令航參數
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
     //4.準備環境,回調SpringApplicationRunListeners的environmentPrepared,表示環境準保完成
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
     //5.打印banner
      Banner printedBanner = printBanner(environment);
     //6.根據環境來決定是創建Web還是IOC容器
      context = createApplicationContext();
      analyzers = new FailureAnalyzers(context);
     //7.準備上下文環境,
     //7.1回調上一步保存的所有ApplicationContextInitializer的initialize方法
     //7.2回調SpringApplicationRunListeners的contextPrepared
     //7.3最後一步回調SpringApplicationRunListeners的contextLoaded
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
     //8.刷新容器(如果是web應用還會創建嵌入式的Tomca).掃描,創建,加載所有組件的地方;(配置類,組件,自動配置)
      refreshContext(context);
     //9.從ioc容器中獲取所有的ApplicationRunner和CommandLineRunner進行回調
      //ApplicationRunner先回調,CommandLineRunner再回調
      afterRefresh(context, applicationArguments);
     //10回調SpringApplicationRunListeners的finished
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
     //整個SpringBoot應用啓動完成以後返回啓動的ioc容器;
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}
  1. 獲取SpringApplicationRunListeners;從類路徑下META-INF/spring.factories
  2. 回調所有的SpringApplicationRunListeners的starting
  3. 封裝命令行參數
  4. 準備環境,回調SpringApplicationRunListeners的environmentPrepared,表示環境準保完成
  5. 打印banner
  6. 根據環境來決定是創建Web還是IOC容器
  7. 準備上下文環境,
  • 7.1回調上一步保存的所有ApplicationContextInitializer的initialize方法
  • 7.2回調SpringApplicationRunListeners的contextPrepared
  • 7.3最後一步回調SpringApplicationRunListeners的contextLoaded
  1. 刷新容器(如果是web應用還會創建嵌入式的Tomca).掃描,創建,加載所有組件的地方;(配置類,組件,自動配置)
  2. 從ioc容器中獲取所有的ApplicationRunner和CommandLineRunner進行回調,ApplicationRunner先回調,CommandLineRunner再回調
  3. 回調SpringApplicationRunListeners的finished
  4. 整個SpringBoot應用啓動完成以後返回啓動的ioc容器;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章