SpringBoot初始加载自动配置类

本文详细介绍了SpringBoot中的配置绑定,包括两种方式:@Component+@ConfigurationProperties和@EnableConfigurationProperties+@ConfigurationProperties。同时,文章深入剖析了SpringBoot自动配置的原理,从@SpringBootApplication注解出发,解析了@SpringBootConfiguration、@ComponentScan和@EnableAutoConfiguration的作用,特别是@EnableAutoConfiguration如何通过@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)进行组件的加载和选择,以及如何按需装配。
摘要由CSDN通过智能技术生成

配置绑定

在开发中,我们习惯于把经常发生变化的东西配置到配置文件里。例如是数据库的用户名,密码,连接池大小等信息。即把properties的JavaBean里,如果使用原生的Java方式来解析,过程太过于繁琐。
原生Java方式来解析:

  1. 创建properties
  2. 通过IO来加载对应的配置信息
  3. 遍历配置文件的Key-Value值再一一赋值给JavaBean

倘若配置文件里有上百行配置信息,我们又单单只需要关于Mysql的配置信息,这样子的方式太过于繁琐。
但是在SpringBoot中,对于配置文件赋值给JavaBean的操作变得简单化了,我们称之为配置绑定。

配置绑定的方式

方式1

@Component+@ConfigurationProperties
举例:
我们先写一个JavaBean

@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
   
    // 品牌
    private String brand;
    // 价格
    private Integer price;

    public String getBrand() {
   
        return brand;
    }

    public void setBrand(String brand) {
   
        this.brand = brand;
    }

    public Integer getPrice() {
   
        return price;
    }

    public void setPrice(Integer price) {
   
        this.price = price;
    }

    @Override
    public String toString() {
   
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

在编写对应的配置文件

mycar.brand = audo
mycar.price = 500000

编写对应的Controller来返回Car

@RequestMapping("/car")
    public Car car(){
   
        return car;
    }

我们启动SpringBoot程序访问/car就能得到对应的配置文件里的信息

请添加图片描述
能得到对应配置文件的信息的原因就是因为我们在Car类上表示了@ConfigurationProperties(prefix = “mycar”)
prefix的含义就是对应的前缀名。前缀名后的属性会去匹配Car类的属性,如果相同就会进行对应的赋值。当然,在这前提必须得是Car被注入进IOC容器中,否则SpringBoot无法对Car提供该功能,@Component也可以被其他注解进行替换,只要能够使得Car被注入进容器中即可。

方式2

@EnableConfigurationProperties+@ConfigurationProperties
@EnableConfigurationProperties 的意思是开启属性配置功能 里面传入你想绑定的JavaBean。
举例

@ConfigurationProperties(prefix = "mycar")
public class Car {
   
    // 品牌
    private String brand;
    // 价格
    private Integer price;

    public String getBrand() {
   
        return brand;
    }

    public void setBrand(String brand) {
   
        this.brand = brand;
    }

    public Integer getPrice() {
   
        return price;
    }

    public void setPrice(Integer price) {
   
        this.price = price;
    }

    @Override
    public String toString() {
   
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

mycar.brand = audo
mycar.price = 500000

写一个对应的配置类

@Component
@EnableConfigurationProperties(Car.class)
public class MyConfig {
   
}

我们启动SpringBoot程序访问/car就能得到对应的配置文件里的信息

请添加图片描述
通过这种方式也可以实现配置文件绑定到对应的JavaBean中。
如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean。说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入。但是在被@EnableConfigurationProperties修饰的类必须得被注入进容器中,否则是无法实现配置绑定的。


自动配置原理

关于SpringBoot的自动配置原理,我们从它的主程序Main方法里进行探究。观察SpringBoot主程序上的注解@SpringBootApplication 可以发现此注解里主要是由三个注解进行合成的

  1. @SpringBootConfiguration
  2. @EnableAutoConfiguration
  3. @ComponentScan

@SpringBootConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration 

我们首先进入@SpringBootConfiguration,可以发现其中最主要的注解就是@Configuration,即声明这个类就是一个配置类,并且该类被注入进IOC容器中,即SpringBoot主程序就是一个配置类。

@ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target({
   ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan 

我们进入@ComponentScan,他就是指定我们要扫描的范围。

@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration 

可以发现@EnableAutoConfiguration 最主要的是有@AutoConfigurationPackage
@Import进行合成的。
我们来看看@AutoConfigurationPackage的作用,其翻译为自动配置包的意思。我们进入其中看看

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
   

我们发现它其实就是一个@Import,在之前的学习中,可以知道@Import的意思就是往容器中导入一个组件,那么AutoConfigurationPackages.Registrar又有什么作用呢?我们再往里继续看看

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
   

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

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

	}

我们发现他其实有两个方法registerBeanDefinitions() 和 determineImports() 其实registerBeanDefinitions()的作用就是批量注册组件进入IOC中我们打断点打在register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]))来查看


请添加图片描述
我们可以看到metadata其实就是注解的原信息,即该注解最终是被标示在哪个类上,可以看见metadata其实就是SpringBoot的主程序。
打断点所在的 new PackageImports(metadata).getPackageNames()的意思就是把我们的metadata拿到后获取其所在的包名。
.toArray(new String[0])即把包名装到一个数组里面,将包下的组件全部注册进IOC中。
这就解释了为什么默认是导入主程序所在包下的组件进入IOC容器里。


接下来我们再来看看@Import(AutoConfigurationImportSelector.class)的作用是什么。
此注解将AutoConfigurationImportSelector注入进IOC容器中,我们进去看看,其中有一个方法

@Override
	public String[] 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值