• SpringBoot自动装配原理


    本文是基于《Spring cloud Alibaba微服务原理与实战》(作者:谭锋)一书中关于SpringBoot的自动装配原理学习了解的。

    1、springBoot自动装配的实现 

      通过IDEA创建一个SpringBoot工程后(或其他方式),就会在主启动类的上方发现@SpringBootApplication这个注解,其实这个注解就像是一个封装的方法。要进入到该注解中去,会发现有一个@EnableAutoConfiguration注解,见名知意,@EnableAutoConfiguration就是用来开启SpringBoot的自动装配的注解。

     1 @SpringBootApplication
     2 public class StaterApplication {
     3 
     4     public static void main(String[] args) {
     5         SpringApplication.run(StaterApplication.class, args);
     6     }
     7 
     8 }


    9 @Target({ElementType.TYPE}) 10 @Retention(RetentionPolicy.RUNTIME) 11 @Documented 12 @Inherited 13 @SpringBootConfiguration 14 @EnableAutoConfiguration 15 @ComponentScan( 16 excludeFilters = {@Filter( 17 type = FilterType.CUSTOM, 18 classes = {TypeExcludeFilter.class} 19 ), @Filter( 20 type = FilterType.CUSTOM, 21 classes = {AutoConfigurationExcludeFilter.class} 22 )} 23 ) 24 public @interface SpringBootApplication { 25 .... 26 }

       接着再进入@EnableAutoConfiguration,有两个重要的注解

         ①、@AutoConfigurationPackage : 作用是把使用了该注解的类所在包以及子包下的所有组件扫描到spring IOC容器中   这也是为什么在创建SpringBoot项目时,一定要把controller、service等都要与主启动类放在同一级目录的原因。

         ②、@Import({AutoConfigurationImportSelector.class})  这个注解才是自动装配的重点,AutoConfigurationImportSelector这个类会实现配置类的导入,导入方式与@Configuration有一定的区别。

        AutoConfigurationImportSelector实现了ImportSelector,它只有一个selectImports方法,返回一个String[]数组,这个数组中可以指定需要装配到IOC容器的类,当在@Import中导入一个ImportSelector的实现类之后,会把该实现类中返回的Class都装配到IoC容器中。和@Configuration不同的是,ImportSelector可以实现批量装配,并且还可以通过逻辑处理来实现Bean的选择性装配,也就是很具上下文环境来决定哪些类能够被IoC初始化。

      1.1简单使用ImportSelector

       首先创建两个类,要把这两个类装配到Ioc容器中

    public class FirstClass{
    
    }
    public class  SecondClass{
    }

       创建一个ImportSelector的实现类,把上述定义的两个Bean加入到String数组,意味着两个Bean会装配到Ioc中

     

     

        自定义一个注解,模拟@EnableAutoConfiguration,通过@Import导入GpImportSelector.

       

     

     

        创建一个启动类,在该类上使用@EnableAutoImport注解后,就可以从Ioc容器中取得FirstClass对象的实例。

     

     

        这种实现方式相比@Import(*Configuration.class)的好处在于装配的灵活性,还可以实现批量装配,比如在G平ImportSelector还可以直接在String数组中定义多个Configuration类,由于一个配置代表的是某一个组件中批量的Bean声明,所以自动装配过程中只需要扫描到指定路径下的配置类即可。

    2、自动装配原理分析

       定位到AutoConfigurationImportSeletor中的selectImpots方法,他是ImportSelector的实现,该方法主要有两个功能:

        ①、AutoConfigurationMetadataLoader.loadMetadata从META-INFO/spring-autoconfigure-metadata.properties中加载自动装配的条件的元数据,就是满足条件的Bean才能够进行装配。

        ②、autoConfigurationEntry.getConfigurations()收集所有符合条件的配置类,完成自动装配

                 需要注意的是,AutoConfigurationImportSeletor中不执行selectImports方法,而是通过ConfigurationClassPostProcessor中的processConfigBeanDefinitions方法来扫描和注册所有的配置类的Bean,最终调用getAutoConfigurationEntry方法来获得所有需要自动装配的配置类。

        以下是getAutoConfigurationEntry方法中几个重要的方法:

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
    return EMPTY_ENTRY;
    } else {
    AnnotationAttributes attributes = this.getAttributes(annotationMetadata);//获得@EnableAutoConfiguration注解的属性exclude、excludeName等

        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);//获得候选的自动装配的配置类
            configurations = this.removeDuplicates(configurations);//去除重复配置项

    Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
    //根据@EnableAutoConfiguration注解的属性exclude等属性,把不需要自动装配的移除

    this.checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);
    configurations = this.getConfigurationClassFilter().filter(configurations);
    this.fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
    }
    }

        总的来说就是,先获取所有的配置类,通过去重、exclude排除等操作,得到最终需要自动装配的配置类。

        getCandidateConfigurations这个方法中使用到了SpringFactoriesLoader,会扫描classpath下的META-INFO/spring.factories文件,spring.factories文件中的数据以key=value形式存储,而SpringFactoriesLoader.loaderFactoryName会根据Key得到对应的value值,因此,key对应为EnableAutoConfiguration,Value是多个配置类,也就是getCandidateConfigurations返回的值。

     省略。。。。。

    另外还使用了许多@ConditionXXX的条件装配的注解

     

    至此,自动装配的原理就分析完了,简单总结一下:

      ①、通过@Import(AutoConfigurationImportSelector.class),导入配置类,这里并不是单个配置类的导入

      ②、AutoConfigurationImportSelector实现了ImportSelector类,重写了selectImports方法,用于实现选择性的批量配置类的装配

      ③、通过Spring的SpringFactoryLoader机制,扫描classpath下的META/spring.factories文件,读取需要实现自动装配的配置类

      ④、通过条件筛选,把不符合的移除,最终实现自动装配

     

     

     

     

  • 相关阅读:
    HDU 1286(欧拉函数||筛选法)
    因数打表(HDU1215)
    HDU 1003
    T行数据跟着N个数据
    15校赛
    HDU 1002
    简单大数相加
    (质因子打表记录素数的位置)HDU Largest prime factor
    HDU cake
    【转】 cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
  • 原文地址:https://www.cnblogs.com/GOOGnine/p/16004217.html
Copyright © 2020-2023  润新知