当前位置 主页 > 服务器问题 > Linux/apache问题 >

    通过代码实例了解SpringBoot启动原理

    栏目:Linux/apache问题 时间:2020-01-04 10:32

    这篇文章主要介绍了通过代码实例了解SpringBoot启动原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    SpringBoot和Spring相比,有着不少优势,比如自动配置,jar直接运行等等。那么SpringBoot到底是怎么启动的呢?

    下面是SpringBoot启动的入口:

    @SpringBootApplication
    public class HelloApplication {
     
      public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
      }
    }

    一、先看一下@SpringBoot注解:

    @Target({ElementType.TYPE})  //定义其使用时机
    @Retention(RetentionPolicy.RUNTIME) //编译程序将Annotation储存于class档中,可由VM使用反射机制的代码所读取和使用。
    @Documented //这个注解应该被 javadoc工具记录
    @Inherited //被注解的类会自动继承. 更具体地说,如果定义注解时使用了 @Inherited 标记,然后用定义的注解来标注另一个父类, 父类又有一个子类(subclass),则父类的所有属性将被继承到它的子类中.
    @SpringBootConfiguration //@SpringBootConfiguration就相当于@Configuration。JavaConfig配置形式
    @EnableAutoConfiguration
    @ComponentScan(
      excludeFilters = {@Filter(
      type = FilterType.CUSTOM,
      classes = {TypeExcludeFilter.class}
    ), @Filter(
      type = FilterType.CUSTOM,
      classes = {AutoConfigurationExcludeFilter.class}
    )} //自动扫描并加载符合条件的组件。以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。
    注:所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。
    )
    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 {};
    }

    所以,实际上SpringBootApplication注解相当于三个注解的组合,@SpringBootConfiguration,@ComponentScan和@EnableAutoConfiguration。

    @SpringBootConfiguration和@ComponentScan,很容易知道它的意思,一个是JavaConfig配置,一个是扫描包。关键在于@EnableAutoConfiguration注解。先来看一下这个注解:

    @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 {};
    }

    Springboot应用启动过程中使用ConfigurationClassParser分析配置类时,如果发现注解中存在@Import(ImportSelector)的情况,就会创建一个相应的ImportSelector对象, 并调用其方法 public String[] selectImports(AnnotationMetadata annotationMetadata), 这里 EnableAutoConfigurationImportSelector的导入@Import(EnableAutoConfigurationImportSelector.class) 就属于这种情况,所以ConfigurationClassParser会实例化一个 EnableAutoConfigurationImportSelector 并调用它的 selectImports() 方法。