SpringBoot 2 系列五:自动配置源码分析

目录

  • 自动配置原理理解
    • 引导加载自动配置类
      • @SpringBootApplication
      • @EnableAutoConfiguration
        • `@AutoConfigurationPackage` 自动配置包注解
        • `AutoConfigurationImportSelector`
    • 按需自动配置
    • 定制化配置
  • 自动配置流程总结

自动配置原理理解

SpringBoot 自动加载所有配置,按照需要加载,如果手动配置了,就以用户配置的为主。每一个配置类都会绑定配置一个 xxxProperties 类,每个 xxxProperties 类对应一个 xxxProperties 配置文件。

引导加载自动配置类

@SpringBootApplication

SpringBoot 应用主程序类上的注解 @SpringBootApplication,表明了程序的入口,这个注解由三个注解组合而成

  • @SpringBootConfiguration
    就是一个 @Configuration
  • @ComponentScan
    指定扫描包
  • @EnableAutoConfiguration
    自动配置注解

@EnableAutoConfiguration

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

@AutoConfigurationPackage 自动配置包注解

// 利用 Registrar 向容器中导入一系列组件 
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

Registar

    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        // 获取到主程序类所在的包,将这个包下的所有组件批量注册到容器中
        // 所以SpringBoot应用默认所有的组件都在 主程序类所在的包下
            AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }

        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
        }
    }

AutoConfigurationImportSelector

// 获取自动配置集合
    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            // 获取所有需要导入容器的组件
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.getConfigurationClassFilter().filter(configurations);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

利用 Map loadSpringFactories(@Nullable ClassLoader classLoader) 方法得到所有的组件,这个方法默认扫描系统里 所有的 META-INF/spring.factories 文件
SpringBoot 2 系列五:自动配置源码分析_第1张图片这个文件在SpringBoot自动配置的核心 spring-boot-autoconfigure-2.3.12.RELEASE.jar 中也有
SpringBoot 2 系列五:自动配置源码分析_第2张图片SpringBoot 启动,默认就会加载所有场景配置,可以按需自动配置

按需自动配置

得益于SpringBoot的按条件配置 @Conditional ,可以根据实际场景加载需要的配置,,并且,当没有手动配置的时候才自动配置
例如:
SpringBoot 2 系列五:自动配置源码分析_第3张图片再例如:
SpringBoot 2 系列五:自动配置源码分析_第4张图片再例如:
SpringBoot 2 系列五:自动配置源码分析_第5张图片Http字符编码过滤器的自动配置
SpringBoot 2 系列五:自动配置源码分析_第6张图片

定制化配置

用户可以自己通过 @Bean 方式替换底层组件
也可以修改组件从配置文件获取的值

自动配置流程总结

导入所有的自动配置类 xxxAutoConfiguration
按需加载组件
组件从 xxxProperties 配置类中获取值
xxxProperties 配置类从 xxxProperties 配置文件获取值

你可能感兴趣的:(Java,spring,boot,java,spring)