一、两个注解对比
@ConfigurationProperties | @Value | |
---|---|---|
来源 | springboot | spring |
功能 | 批量注入配置文件中的属性 | 一个个的单独指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
注意:配置文件不管是yml格式还是properties格式,上面两种注解都可以获取的到。
二、来源
package org.springframework.boot.context.properties.ConfigurationProperties {}
package org.springframework.beans.factory.annotation.Value {}
三、功能
1、@ConfigurationProperties
指定一个前缀,将配置文件里前缀后面的所有属性都一一映射到JavaBean对应的属性中。
比如:
配置:
person:
lastName: 张三
age: 25
isBoss: false
birth: 2017/12/12
maps: {key1: value1,key2: value2}
lists:
- 雷军
- 乔布斯
- 马云
dog:
name: milly
age: 2
JavaBean:
@ConfigurationProperties(prefix = "person")
@Component
public class Person {
// 这种驼峰写法在yml里可以用lastName或者last-name,都可以
private String lastName;
private Integer age;
private boolean isBoss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
...省略getter/setter/toString...
}
PS:需要将Person指定为SpringBean,@ConfigurationProperties才会生效。
测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot02ConfigApplicationTests {
@Autowired
private Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
}
测试结果:
Person{lastName='张三', age=25, isBoss=false, birth=Tue Dec 12 00:00:00 CST 2017, maps={key1=value1, key2=value2}, lists=[雷军, 乔布斯, 马云], dog=Dog{name='milly', age=2}}
PS:结果发现我们配置文件里的属性值都赋值到了JavaBean中,符合预期。
2、@Value
类似于Spring配置文件的value属性:
<bean class="Person">
<property name="lastName" value="zhangsan"></property>
</bean>
要想完成JavaBean和配置文件的映射,需要在JavaBean中的每个属性上都写上@Value,进行一一匹配。
配置:
同@ConfigurationProperties的配置
JavaBean:
@Component
public class Person {
@Value("person.lastName")
private String lastName;
@Value("person.age")
private Integer age;
@Value("person.isBoss")
private boolean isBoss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
...省略getter/setter/toString...
}
PS:只写了前几个,效果很明显,我们需要写很多@Value注解,在每个属性上都写上,很麻烦。
测试类:
同@ConfigurationProperties的配置
四、松散绑定
1、定义
比如JavaBean里写的是lastName(驼峰写法),配置文件里可以写成lastName,也可以写成last-name。
2、证明
2.1、@ConfigurationProperties
配置:
person:
last-name: 张三
JavaBean:
@ConfigurationProperties(prefix = "person")
@Component
public class Person {
// 这种驼峰写法在yml里可以用lastName或者last-name,都可以
private String lastName;
}
运行测试类, 依然可以正常赋值。
2.2、@Value
配置:
person:
last-name: 张三
JavaBean:
@Component
public class Person {
@Value("${person.lastName}")
private String lastName;
}
运行测试类,启动会报错
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'person.lastName' in value "${person.lastName}"
五、SpEL
1、@ConfigurationProperties
不支持SpEL表达式,比如年龄字段若写成:#{22 * 2},会出错。
2、@Value
支持SpEL表达式,比如:
@Component
public class Person {
@Value("#{22*2}")
private Integer age;
}
输出年龄:44
六、JSR303数据校验
1、@ConfigurationProperties
配置:
person:
lastName: 张三
age: 25
isBoss: false
birth: 2017/12/12
maps: {key1: value1,key2: value2}
lists:
- 雷军
- 乔布斯
- 马云
dog:
name: milly
age: 2
JavaBean:
@ConfigurationProperties(prefix = "person")
@Component
@Validated
public class Person {
@Email
private String lastName;
private Integer age;
private boolean isBoss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
...省略getter/setter/toString...
}
测试结果:
- Field error in object 'person' on field 'lastName': rejected value [张三]; codes [Email.person.lastName,Email.lastName,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [person.lastName,lastName]; arguments []; default message [lastName],[Ljavax.validation.constraints.Pattern$Flag;@54336c81,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@1556f2dd]; default message [不是一个合法的电子邮件地址]; origin class path resource [application.yml]:6:14
2、@Value
配置:
同@ConfigurationProperties的配置
JavaBean:
@Component
@Validated
public class Person {
@Email
@Value("${person.last-name}")
private String lastName;
private Integer age;
private boolean isBoss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
...省略getter/setter/toString...
}
测试结果:
不会出现异常
七、复杂类型封装
1、什么是复杂类型?
比如person里有个maps
2、@ConfigurationProperties
配置:
person:
maps: {key1: value1,key2: value2}
JavaBean:
@ConfigurationProperties(prefix = "person")
@Component
public class Person {
private Map<String, Object> maps;
}
运行结果:会正常给maps赋值。
3、@Value
配置:
person:
maps: {key1: value1,key2: value2}
JavaBean:
@Component
public class Person {
@Value("${person.maps}")
private Map<String, Object> maps;
}
运行结果:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'person.mps' in value "${person.mps}"
八、建议
1、如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value。简单粗暴。
2、如果说,我们专门编写了一个JavaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties注解进行映射。
九、广告
-
QQ群【Java初学者学习交流群】:458430385
-
微信公众号【Java码农社区】
- 今日头条号:编程界的小学生
网友评论