美文网首页java面试
SpringBoot2.0 自动配置原理

SpringBoot2.0 自动配置原理

作者: bit_拳倾天下 | 来源:发表于2021-03-20 18:51 被阅读0次

    1. 依赖管理

    SpringBoot 最方便的地方就是 自动配置互补配置,而自动配置的前提是有这些东西才能配置,也就是必须要有相应的依赖。

    SpringBoot 有各种各样的场景启动器,这些启动器里边根据场景的需求帮我们引入了各种依赖。
    所以我们只需要对应场景选择启动器即可完成大多数依赖的引入,而且spring-boot-starter-parent => spring-boot-dependencies 里面定义了依赖相应的m默认版本,但是我们又能够自定义版本。
    各种场景启动器都会依赖spring-boot-starter,而spring-boot-starter 又会依赖 spring-boot-autoconfigure,后者就是用于自动配置的。

    总之:

    1. 场景启动器里边配置依赖;
    2. 场景启动器所依赖的 spring-boot-autoconfigure 帮助自动配置;
    3. 父项目中的 spring-boot-dependencies 管理依赖的版本

    2. 自动配置

    2.1 关于容器注入和属性绑定的几种注解

    1) @Configuration + @Bean

    @Configuration 标注在配置类上,声明这个类是一个配置类,本质上也是容器中的组件(@Component)。其中一个属性proxyBeanMethods,默认为true,含义是是否需要代理,就是是否为单例,true 代表单例,false 代表不是单例。

    @Bean 标注在配置类方法上,用于给容器中注入组件,类型为方法返回值类型,组件名称默认为方法名,也可以自定义组件名。

    2)@Import

    标注在类上,也是为容器中注入组件,前提是该类也是容器中的一个组件(@Configuration,@Component 等等都实行),属性 value 是一个 Class 数组,用于指定注入哪些类型的组件,组件名和类同名但首字母小写。
    通常直接在 @Import 的 value 中指定需要导入的类型即可,但有的时候类型太多或者不固定,就不适合直接写导入的类了,可以用下面两种方法。

    a. 借助 ImportSelector

    实现 ImportSelector 接口,它有一个 selectImports 方法,用于返回想要导入的容器的全类名字符串数组。使用时只要把这个 Selector 填入 @Import 即可借助 @Import 将这些类注入

    public interface ImportSelector {
        String[] selectImports(AnnotationMetadata var1);
    
        @Nullable
        default Predicate<String> getExclusionFilter() {
            return null;
        }
    }
    
    b. 借助 ImportBeanDefinitionRegistrar

    实现 ImportBeanDefinitionRegistrar,实现 registerBeanDefinitions 方法,利用 registry.registerBeanDefinition() 将想要注入的组件注册,然后将这个 Registar 填入 @Import value 中即可。

    public interface ImportBeanDefinitionRegistrar {
        default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
            this.registerBeanDefinitions(importingClassMetadata, registry);
        }
    
        default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        }
    }
    
    //例子
    public class SelfImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            //想要住放入的类,需要通过 BeanDefinition 包装一下,
            RootBeanDefinition root = new RootBeanDefinition(Test.class);
            registry.registerBeanDefinition("组件名", root);
        }
    }
    

    3)@Conditional

    标注与配置类或组件上面(@Configuration, @Bean...),用于条件装配,满足一定条件才注入,


    image.png

    4)@ImportResource

    用于引入原生的配置文件。如 XXX.xml 这种形式的文件,里面注入的组件,SpringBoot 是不能直接获取的,利用这个注解,可以使其生效,属性 locations 是配置文件路径的字符数组。

    @ImportResource("classpath:beans.xml")
    

    5)@ConfigurationProperties,@Value

    @Value 标注在属性上,从配置文件中读取数据赋值给属性@ConfigurationProperties 标注类上,可以从配置文件中读取信息,绑定到类的属性中,使其生效的方法有两种:

    a. 标注在组件上

    也就是说这个类不止要被 @ConfigurationProperties 修饰,还要是一个组件(@Configuration,@Component...)。

    b. 配合 @EnableConfigurationProperties

    在某个配置类上,用 @EnableConfigurationProperties 标注,并把 @ConfigurationProperties 标注的类的 class 填入到 @EnableConfigurationProperties 的属性中即可。
    这个注解有两个作用:
    1、开启 @ConfigurationProperties 标注类的配置绑定功能
    2、把这个类的组件自动注册到容器中

    6)@ComponentScan

    用来指定 Spring 扫描的包,也就是扫描范围,默认是 @Component 注解所在的同级及以下目录

    2.2 自动注入的关键,@SpringBootApplication

    //说明@SpringBootApplication也是个配置类
    @SpringBootConfiguration
    //开启自动配置
    @EnableAutoConfiguration
    //包扫描
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    

    @ComponentScan 在不指定扫描路径的情况下,默认扫描标注类的同级及以下的路径。可以通过 @SpringBootApplication 的 scanBasePages 属性自定义扫描路径。

    //自动配置包
    @AutoConfigurationPackage
    //导入一个 Selector
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    

    导入了一个 AutoConfigurationImportSelector 组件,这个组件会总 "META-INF/spring.factories" 文件中读取 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的值,里边是各种 XXXAutoConfiguration的全类名。所以它就是用来帮我们导入大量的配置类的。

    @Import(AutoConfigurationPackages.Registrar.class)
    public @interface AutoConfigurationPackage {
    

    这里又导入了一个 AutoConfigurationPackages.Registrar,这个大致就是为当前项目包下的所有组件,如果配置了 scanBasePackages 就用配置的包,没有配置就用主配置类所在的包。

    总结:

    @SpringBootApplication 帮我们开启了自动配置和组件导入。
    借助 @Import 和 AutoConfigurationImportSelector 导入各种 AutoConfiguration 组件,用于自动配置。
    借助 @Import 和 AutoConfigurationPackages.Registrar 导入当前项目包路径中的组件。

    3. 自动配置

    @SpringBootApplication 从 spring-boot-autoconfigure 中获取并注入各种 AutoConfiguration 组件,用来自动配置,里边会利用 2.1 中的几种注解实现自动配置,互补配制和条件装配。例如:Servlet 容器自动配置的例子解析

    相关文章

      网友评论

        本文标题:SpringBoot2.0 自动配置原理

        本文链接:https://www.haomeiwen.com/subject/dzsycltx.html