您的位置:首页 > 编程语言 > Java开发

Spring Boot 2.X自动装配浅析

2020-07-15 06:16 330 查看
  • 什么是自动配置?

      SpringBoot所谓的自动配置是基于JavaConfig技术(配置类 + 注解的方式)的,而不是XML。e.g SpringFramework官方文档中的示例DispatcherServlet的JavaConfiguration配置方式与XML方式配置
    1. SpringBoot会根据当前环境(依赖)自动应用一些JavaConfig来做配置。
    2. SpringBoot会通过一些条件筛选判断是否需要某个配置(动态插拔的体现)。e.g SpringBoot Application启动类上的@Enable***
  • 原理

    从启动类入手

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

    @SpringBoot是一个复合注解,其中有

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    // 以上为原注解
    @SpringBootConfiguration // 表明当前类是一个根配置类(级别较@Configuration高)
    @EnableAutoConfiguration
    @ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
    ), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
    )}
    )
    public @interface SpringBootApplication { ... ...}

    进入@EnableAutoConfiguration中

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    // 以上为原注解
    @AutoConfigurationPackage // 作用是自动加载扫描包的路径(这也是为什么SpringBoot应用的启动类总是在最外层的原因)
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {... ...}

    而@Import注解会将AutoConfigurationImportSelector.class注入到IOC容器中
    要注意,关键点来了
    深入AutoConfigurationImportSelector内部

    public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    ... ...
    // 此方法实现至DeferredImportSelector接口
    // 而DeferredImportSelector又继承自ImportSelector接口
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
    return NO_IMPORTS;
    } else {
    AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
    }
    ... ...
    }

    ImportSelector接口:SpringBoot自动配置的核心

    public interface ImportSelector {
    // 返回一个String数组,数组里的内容是一些类的路径名称,Spring会把这个数组返回的路径名称的类加载注入到IOC容器中
    String[] selectImports(AnnotationMetadata var1);
    ... ...
    }

    String[ ] selectImports 是如何加载类路径信息的?

    AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);

    this.getAutoConfigurationEntry(annotationMetadata)

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    ... ...
    List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
    ... ...
    }
    }

    this.getCandidateConfigurations(annotationMetadata, attributes)

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    ... ...
    }

    loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(),this.getBeanClassLoader())会找到spring.factories

    第一个参数返回值确定类型org.springframework.boot.autoconfigure.EnableAutoConfiguration

    protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    // 会根据这个类型找到对应的配置类的路径
    return EnableAutoConfiguration.class;
    }


所以 String[] selectImports 方法会扫描到这个文件,将类型匹配的配置类加载到IOC容器中,从而可以让开发者做到“开箱即用”

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: