在基于 SpringBoot 进行开发的过程中,经常遇到需要在类中读取配置文件参数的情况。我们可以用 @Value 注解来指定需要读取的配置文件:

yml文件

yml文件中:

  1. # application-dev.yml
  2. aliyun:
  3. accessKey:
  4. id: "xxx"
  5. secret: "xxx"

@Value注解

类中使用 @Value 读取:

  1. // 需要读取的类中
  2. public class test {
  3. @Value("aliyun.accessKey.id")
  4. private String accessKeyId;
  5. @Value("aliyun.accessKey.secret")
  6. private String accessKeySecret;
  7. }

以上可以读取到yml中到参数,并使用,需要注意的是,变量不能使用 static 修饰,不然会发生无法注入的情况,原因:

  1. 类的静态变量只会在类加载的时候初始化,而且只会初始化一次,因此静态变量是属于类的属性,而不是属于实例的属性
  2. Spring的依赖注入是基于对象实例层面的

但可以通过set方法在注入时来改变静态变量的值:

  1. // 需要读取的类中
  2. public class test {
  3. private String accessKeyId;
  4. private String accessKeySecret;
  5. @Value("aliyun.accessKey.id")
  6. public void setAccessKeyId(String accessKeyId) {
  7. this.accesskeyId = accessKeyId;
  8. }
  9. }

@ConfigurationProperties 注解

使用 @ConfigurationProperties 可以通过字段名来直接跟配置文件中的 key 绑定,从而获取 value 值,例如:

  1. // 需要读取的类中
  2. @ConfigurationProperties(prefix = "aliyun.accessKey")
  3. public class Test {
  4. // 属性名对应yml中的key,spring将会自动注入
  5. private String accesskeyId;
  6. private String accessKeySecret;
  7. }

属性多的话,@ConfigurationProperties 显然更好一些,可以减少代码量,也更加直观,在Spring的官方文档中,也对比了 @Value 和 @ConfigurationProperties 的异同,如下

两者对比

  1. 引用自 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可以匹配到更多类型写法,也会更加灵活

  1. 微服务架构下,通常会使用配置中心来热更新配置,在这一基础下,这两个注解也有所不同,如果使用的是 @ConfigurationProperties ,更改了配置中心的配置后,会自动热更新,但是使用 @Value 无法实现,需要在类上加注解 @RefreshScope(背后的实现是给对象加了一层代理, 每当配置发生更新时将旧的对象销毁后重建一个新对象,代价大,建议使用 @ConfigurationProperties)