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文件,读取需要实现自动装配的配置类

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

 

 

 

 

posted @ 2022-03-14 17:14  灯下一个人  阅读(1106)  评论(0编辑  收藏  举报