配置绑定
在开发中,我们习惯于把经常发生变化的东西配置到配置文件里。例如是数据库的用户名,密码,连接池大小等信息。即把properties的JavaBean里,如果使用原生的Java方式来解析,过程太过于繁琐。
原生Java方式来解析:
- 创建properties
- 通过IO来加载对应的配置信息
- 遍历配置文件的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 可以发现此注解里主要是由三个注解进行合成的
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @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[]