在基于 SpringBoot 进行开发的过程中,经常遇到需要在类中读取配置文件参数的情况。我们可以用 @Value 注解来指定需要读取的配置文件:
yml文件
yml文件中:
# application-dev.yml
aliyun:
accessKey:
id: "xxx"
secret: "xxx"
@Value注解
类中使用 @Value 读取:
// 需要读取的类中
public class test {
@Value("aliyun.accessKey.id")
private String accessKeyId;
@Value("aliyun.accessKey.secret")
private String accessKeySecret;
}
以上可以读取到yml中到参数,并使用,需要注意的是,变量不能使用 static 修饰,不然会发生无法注入的情况,原因:
- 类的静态变量只会在类加载的时候初始化,而且只会初始化一次,因此静态变量是属于类的属性,而不是属于实例的属性
- Spring的依赖注入是基于对象实例层面的
但可以通过set方法在注入时来改变静态变量的值:
// 需要读取的类中
public class test {
private String accessKeyId;
private String accessKeySecret;
@Value("aliyun.accessKey.id")
public void setAccessKeyId(String accessKeyId) {
this.accesskeyId = accessKeyId;
}
}
@ConfigurationProperties 注解
使用 @ConfigurationProperties 可以通过字段名来直接跟配置文件中的 key 绑定,从而获取 value 值,例如:
// 需要读取的类中
@ConfigurationProperties(prefix = "aliyun.accessKey")
public class Test {
// 属性名对应yml中的key,spring将会自动注入
private String accesskeyId;
private String accessKeySecret;
}
属性多的话,@ConfigurationProperties 显然更好一些,可以减少代码量,也更加直观,在Spring的官方文档中,也对比了 @Value 和 @ConfigurationProperties 的异同,如下
两者对比
- 引用自 SpringBoot 官方文档:
If you define a set of configuration keys for your own components, we recommend you group them in a POJO annotated with @ConfigurationProperties. Doing so will provide you with structured, type-safe object that you can inject into your own beans.
如果你为自己的组件定义了一组配置键,我们建议你将它们归入一个用@ConfigurationProperties注解的POJO中。这样做将为你提供结构化的、类型安全的对象,你可以将其注入到你自己的bean中。
Spring官方建议将 @ConfigurationProperties 用在POJO实体中
If you do want to use @Value, we recommend that you refer to property names using their canonical form (kebab-case using only lowercase letters). This will allow Spring Boot to use the same logic as it does when relaxed binding @ConfigurationProperties.For example, @Value(“{demo.item-price}”) will pick up demo.item-price and demo.itemPrice forms from the application.properties file, as well as DEMO_ITEMPRICE from the system environment. If you used @Value(“{demo.itemPrice}”) instead, demo.item-price and DEMO_ITEMPRICE would not be considered.
如果你确实想使用@Value,我们建议你使用它们的规范形式来引用属性名(只使用小写字母的短横线命名,例如:access-key)。这将允许Spring Boot使用与relaxed binding模式@ConfigurationProperties时相同的逻辑。后面一段举例就不翻译了,意思就是使用kebab-case模式spring可以匹配到更多类型写法,也会更加灵活
- 微服务架构下,通常会使用配置中心来热更新配置,在这一基础下,这两个注解也有所不同,如果使用的是 @ConfigurationProperties ,更改了配置中心的配置后,会自动热更新,但是使用 @Value 无法实现,需要在类上加注解 @RefreshScope(背后的实现是给对象加了一层代理, 每当配置发生更新时将旧的对象销毁后重建一个新对象,代价大,建议使用 @ConfigurationProperties)