美文网首页
Spring Boot启动流程

Spring Boot启动流程

作者: hTangle | 来源:发表于2019-04-09 22:30 被阅读0次

    Spring Boot的启动函数如下所示

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
    
    @SpringBootApplication
    public class NevergetmewebApplication extends SpringBootServletInitializer {
        public static void main(String[] args) {
            SpringApplication.run(NevergetmewebApplication.class, args);
        }
    }
    

    以上代码很容易看出哪些是关键,当然是@SpringBootApplication和application.run()分别是springboot加载配置和启动,下面详细说明这两块。
    首先是SpringBootApplication.class

    package org.springframework.boot.autoconfigure;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.boot.context.TypeExcludeFilter;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.core.annotation.AliasFor;
    
    @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 {
        @AliasFor(
            annotation = EnableAutoConfiguration.class
        )
        Class<?>[] exclude() default {};
    
        @AliasFor(
            annotation = EnableAutoConfiguration.class
        )
        String[] excludeName() default {};
    
        @AliasFor(
            annotation = ComponentScan.class,
            attribute = "basePackages"
        )
        String[] scanBasePackages() default {};
    
        @AliasFor(
            annotation = ComponentScan.class,
            attribute = "basePackageClasses"
        )
        Class<?>[] scanBasePackageClasses() default {};
    }
    

    其中@Configuration(@SpringBootConfiguration中其实用的也是@Configuration);@EnableAutoConfiguration;@ComponentScan三个是最重要的注解,@SpringBootApplication整合了三个注解使用者写起来看起来都比较简洁

    @Configuration

    它就是JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,这里的启动类标注了@Configuration之后,本身其实也是一个IoC容器的配置类。

    @EnableAutoConfiguration

    EnableAutoConfiguration.class

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import org.springframework.context.annotation.Import;
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
        Class<?>[] exclude() default {};
    
        String[] excludeName() default {};
    }
    

    @EnableAutoConfiguration简单的说它的作用就是借助@Import的支持,收集和注册特定场景相关的bean定义。其中,最关键的要属@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持很智能的自动配置:


    image.png

    SpringFactoriesLoader其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

    springboot启动简单流程

    1. 启动类里面调用SpringApplication.run(xxx.class,args)方法
    2. 在SpringApplicaiton的run方法中有两个步骤,首先创建SpringApplicaiton对象,然后再调用run方法。
        public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
            return (new SpringApplication(primarySources)).run(args);
        }
    
    public SpringApplication(Class... primarySources) {
            this((ResourceLoader)null, primarySources);
        }
    
        public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
            this.sources = new LinkedHashSet();
            this.bannerMode = Mode.CONSOLE;
            this.logStartupInfo = true;
            this.addCommandLineProperties = true;
            this.addConversionService = true;
            this.headless = true;
            this.registerShutdownHook = true;
            this.additionalProfiles = new HashSet();
            this.isCustomEnvironment = false;
            this.resourceLoader = resourceLoader;
            Assert.notNull(primarySources, "PrimarySources must not be null");
            this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
            this.webApplicationType = WebApplicationType.deduceFromClasspath();
            this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
            this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
            this.mainApplicationClass = this.deduceMainApplicationClass();
        }
    
    1. 在SpringApplicaiton构造器中调用initialize(sources)方法。
    2. initialize方法中,
      a. 将sources转换成list加到this.sources属性中
      b. 判断是否为web环境(在类路径下是否可以加载到Servlet和ConfigurableWebApplicationContext)
      c. 加载Initializers(通过META-INF/spring.factories中键为ApplicationContextInitializer的配置进行加载),dubug发现一共
      加载了6个initializer(spring-boot-1.5.10.RELEASE.jar中4个,spring-boot-autoconfigure-1.5.10.RELEASE.jar中2个)
      d. 加载ApplicationListener(也是通过META-INF/spring.factories),debug发现共加载了10个
      e. 通过寻找main方法找到启动主类。
    3. run方法中
      a. StopWatch主要是监控启动过程,统计启动时间,检测应用是否已经启动或者停止。
      b. 加载SpringApplicationRunListener(也是通过META-INF/spring.factories),默认加载的是EventPublishingRunListener
      c. 调用RunListener.starting()方法。
      d. 根据args创建应用参数解析器ApplicationArguments;
      e. 准备环境变量:获取环境变量environment,将应用参数放入到环境变量持有对象中,监听器监听环境变量对象的变化(listener.environmentPrepared)
      f. 打印Banner信息(SpringBootBanner)
      g. 创建SpringBoot的应用上下文(AnnotationConfigEmbeddedWebApplicationContext)
      h.prepareContext上下文之前的准备
      i. refreshContext刷新上下文
      j. afterRefresh(ApplicationRunner,CommandLineRunner接口实现类的启动)
      k. 返回上下文对象

    相关文章

      网友评论

          本文标题:Spring Boot启动流程

          本文链接:https://www.haomeiwen.com/subject/qhuwiqtx.html