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容器;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值