• Spring Boot 自动配置原理


    一、主程序类,主入口类

    入口类中有一个main方法,这个方法其实就是一个标准的Java应用的入口方法,一般在main方法中使用SpringApplication.run()来启动整个应用。
    值得注意的是,这个入口类要使用@SpringBootApplication注解声明,它是SpringBoot的核心注解。
    /**
     *  @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应用;

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

    @SpringBootConfiguration:Spring Boot的配置类;

        标注在某个类上,表示这是一个Spring Boot的配置类;

            @Configuration:配置类上来标注这个注解;

             配置类 ----- 配置文件;配置类也是容器中的一个组件;@Component

     

    @EnableAutoConfiguration:开启自动配置功能;

              以前我们需要配置的东西,Spring Boot帮我们自动配置;

             @EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效;

    @AutoConfigurationPackage
    @Import(EnableAutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    }

    @AutoConfigurationPackage:自动配置包,扫描启动类下面的所有的注解

    @Import(AutoConfigurationPackages.Registrar.class):

    Spring的底层注解@Import,给容器中导入一个组件;导入的组件由AutoConfigurationPackages.Registrar.class;

    将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;

    @Import(EnableAutoConfigurationImportSelector.class);

     

    EnableAutoConfigurationImportSelector:导入哪些组件的选择器;

    可以看到,在@EnableAutoConfiguration注解内使用到了@import注解来完成导入配置的功能,
    而EnableAutoConfigurationImportSelector内部则是使用了SpringFactoriesLoader.loadFactoryNames方法进行扫描具有META-INF/spring.factories文件的jar包。
    下面是1.5.8.RELEASE实现源码:
     
     @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        try {
              AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                        .loadMetadata(this.beanClassLoader);
              AnnotationAttributes attributes = getAttributes(annotationMetadata);
              //扫描具有META-INF/spring.factories文件的jar包
              List<String> configurations = getCandidateConfigurations(annotationMetadata,
                        attributes);
              //去重
              configurations = removeDuplicates(configurations);
              //排序
              configurations = sort(configurations, autoConfigurationMetadata);
               //删除需要排除的类
             Set<String> exclusions = getExclusions(annotationMetadata, attributes);
             checkExcludedClasses(configurations, exclusions);
             configurations.removeAll(exclusions);
             configurations = filter(configurations, autoConfigurationMetadata);
             fireAutoConfigurationImportEvents(configurations, exclusions);
             return configurations.toArray(new String[configurations.size()]);
        }
        catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

    //加载spring.factories实现
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
        Assert.notEmpty(configurations,
                "No auto configuration classes found in META-INF/spring.factories. If you "
                          + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }
     

     

     

     

    上面的EnableAutoConfiguration配置了多个类,这些都是Spring Boot中的自动配置相关类;在启动过程中会解析对应类配置信息。
    每个Configuation类都定义了相关bean的实例化配置。都说明了哪些bean可以被自动配置,什么条件下可以自动配置,并把这些bean实例化出来。
    如果我们自定义了一个starter的话,也要在该starter的jar包中提供 spring.factories文件,并且为其配置org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置类。
    所有框架的自动配置流程基本都是一样的,判断是否引入框架,获取配置参数,根据配置参数初始化框架相应组件。

    将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;

    会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件; 

    有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;

    SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);

     

    Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作;以前我们需要自己配置的东西,自动配置类都帮我们;

  • 相关阅读:
    Cocos2dx-demo演示项目:Part2
    利用Python抓取亚马逊评论列表数据
    Cocos2dx-demo演示项目:Part1
    正则表达式匹配原理
    js正则函数中test和match的区别
    【别人家的孩子系列之】浅析正则表达式—(原理篇)
    JS 获取浏览器窗口大小
    javascript的insertBefore、insertAfter和appendChild简单介绍
    javascript 限制字符串字数换行 带BUG
    一行一行分析JQ源码学习笔记-06
  • 原文地址:https://www.cnblogs.com/dalianpai/p/11772065.html
Copyright © 2020-2023  润新知