…
一、引言在SpringBoot
的自动配置中,有两个分量很重的注解 @ConfigurationProperties
和 @EnableConfigurationProperties
。这两个注解能干嘛呢?它们的原理又是什么呢?下面本文就来学习一下。
在学习@ConfigurationProperties
之前,先来回想一下在Spring
中读取配置属性的方式有哪些?是不是立刻就会想到@Value
注解?对,就是这个注解。
下面对@Value
,@PropertySource
、@ConfigurationProperties
等相关注解进行学习介绍。
@Value
注解非常有用,它的用法也非常多,但这里只介绍一种情况,也是本人在开发中最常用的情况,至于其他使用方式,例如:普通字符串的注入和表达式的注入意义不是很大,此处不做过多介绍。
@Value
注解最常用的一种方式,就是将配置文件中自定义的属性值注入到特定属性中,下面直接上代码。 解释一下:在
application.properties
配置文件中,自定义了一个属性person.name
,通过@Value注解
,就可以将这个配置文件中自定义的值映射到代码中的属性上。
上面这种方式,就是本人在日常开发中最常用的方式。那么什么情况下会用到这个@Value注解
呢?可配置属性。例如,现在有个功能是要接受客户端上传上来的文件,存放文件的目录要求可以动态配置,不能在代码中写死,是不是想到这个注解了?
这里需要注意的是:在使用${ key }去获取值时,如果 key 找不到,启动会失败,这样是不对的,我们不能因为一个属性没有配置而让项目无法启动。所以,我们可以给它一个默认值,就如下面的配置,如果person.name
拿不到值,就用scorpios
作为默认值。
@Value("${person.name:scorpios}")
String name;
2、@PropertySource:加载配置属性源
@PropertySource
注解也是非常非常的强大,通过@PropertySource
注解可以把配置文件加载进来,然后使用@Value
获取其中的属性值。
在上面的例子,@Value
注解获取属性值是从application.properties
配置文件中获取的。如果现在我们不在配置文件中配置这些属性,而是单独放在一个文件中,怎么办呢?看下面代码:
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.name}")
private String name;
@Value("${jdbc.password}")
private String password;
public String print(){
return name + "-" + password;
}
是不是不用讲就已经明白
@PropertySource
的使用了?哈哈~~~~~ 下面来对@PropertySource
各属性介绍:
-
value:数组。用于指定配置文件的位置。支持
classpath:
和file:
等前缀,Spring
发现是classpath
开头的,因此最终使用的是Resource
的子类ClassPathResource
。如果是file
开头的,则最终使用的类是FileSystemResource
。 -
ignoreResourceNotFound:默认值false。表示如果没有找到文件就报错,若改为true就不报错。建议保留false。
-
encoding:加载进来的编码。一般不用设置,可以设置为UTF-8等等
-
factory:默认的值为
DefaultPropertySourceFactory.class
。
注意:上面两个注解都是Spring Framwork
提供的功能。而@ConfigurationProperties
是Spring Boot
提供的。包括@EnableConfigurationProperties
也是Spring Boot
才有的。它在自动化配置中起到了非常关键的作用。
@ConfigurationProperties
的作用就是,它可以把配置文件中的配置信息自动封装成对应的实体类,来看一下例子。(☆☆☆☆☆)
// application.properties配置文件中的配置属性
test.people.name=scorpios
test.people.age=30
test.people.address[0]=上海
test.people.address[1]=南京
test.people.address[2]=苏州
// 要封装的实体类
@Component // 注意一下这个注解!!!!
@ConfigurationProperties(prefix = "test.people")
public class People {
private String name;
private Integer age;
private List address;
// setter / getter / toString 方法省略
}
同样的问题,如果不在
application.properties
配置文件中指定这些属性值,而是需要额外指定配置文件,就需要结合@PropertySource注解
使用,结果依然可以。
@Component // 注意一下这个注解!!!!
@ConfigurationProperties(prefix = "test.people")
@PropertySource(value = {"classpath:people.properties"})
public class People {
private String name;
private Integer age;
private List address;
}
在读Spring源码时,关注ConfigurationPropertiesBindingPostProcessor后置处理器,它会对标注@ConfigurationProperties注解的Bean进行属性值配置。
上面的代码中,在使用@ConfigurationProperties
注解时,特意强调了一下要加@Component
注解。如果不加@Component
这个注解,在启动程序时会报错。这能说明什么问题呢?
这能说明:@ConfigurationProperties注解
主要作用是把properties配置文件
赋值给SpringIOC容器
中的Bean的,这个注解作用的前提条件就是这个实体类必须已经转化为了Bean,并且已经存在与SpingIOC容器中。
但是!!!当我们在看SpringBoot
自动配置源码时,并没有看到属性类上面加了这个@Component注解
!!!(不信的话,可以去查看各个自动配置类需要用到的对应***Properties类,这里我只放两个类),这是为什么呢?这就涉及到SpringBoot的自动装配原理了。
好了,下面要引入
@EnableConfigurationProperties注解
,这个注解的作用是让@ConfigurationProperties注解
生效。什么意思呢?
就是说如果我们在需要映射的实体类上只标注了@ConfigurationProperties注解
,但是这个实体类并没有转化为Bean
存在于SpringIOC容器
中,这个注解是没有用的(会报错),也就是说属性绑定会失败。(能理解此处的Bean的意思么?)
这里先说一下,用@EnableConfigurationProperties注解
会将对应的实体类转为Bean加入到SpringIOC容器
中,如下所示。至于为什么?且听下回分解。
终于讲完啦。。。。。理解了么?
三、小结 简单总结一下1、@ConfigurationProperties注解
是将application配置文件
的某类名下所有的属性值,自动封装到实体类中。这个注解作用的前提条件就是,实体类已经转化为Bean
存在于SpringIOC容器
中。
2、@EnableConfigurationProperties注解
的作用是让@ConfigurationProperties注解
生效。也就是让@ConfigurationProperties注解
绑定的实体类转为为Bean
交给SpingIOC容器
管理。从而让@ConfigurationProperties注解
生效。
3、@Value
是将application配置
文件中,所需要的某个属性值,封装到Java代码
中以供使用。
此注解的作用是导入Spring的配置文件
,让配置文件里面的内容生效。此注解常常在老的Spring项目
往SpringBoot项目
迁移过程中使用。因为 Spring Boot
里面根本就没有Spring的配置文件
,我们自己编写的配置文件,SpringBoot
也不能自动识别。
所以想让Spring的配置文件
生效,就需要使用@ImportResource注解
,此注解标注在一个配置类上即可。
// 导入Spring的配置文件让其生效
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}