0
点赞
收藏
分享

微信扫一扫

SpringBoot2.0 自动配置原理

花明 2021-09-30 阅读 88

1. 依赖管理

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

总之:

  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...),用于条件装配,满足一定条件才注入,


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、把这个类的组件自动注册到容器中

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 容器自动配置的例子解析

举报

相关推荐

0 条评论