天天看點

Spring中的@Value和@ConfigurationProperties你是不是用不明白?

作者:JAVA旭陽

概述

相信大家在在各自的項目中都使用過@Value和@ConfigurationProperties兩個注解,他們可以自動從我們的配置檔案中擷取配置資訊,那他們之間有什麼差別呢,我們該優先選擇哪種方式來讀取配置呢?

差別

兩個注解的使用方式和源碼解析可以參考下面的兩個文章,本篇我們重點關注在他們的差別上。

@Value的使用: 一文深入了解Spring中的@Value注解

@ConfigurationProperties的使用: 一文深入了解ConfigurationProperties注解

比較項 @Value @ConfigurationProperties
使用方式 需要一個個指定 能夠批量地注入配置檔案中的屬性
所屬架構 Spring Spring Boot
SPEL 支援 不支援
JSR303資料校驗 不支援 支援
松散綁定 不支援 支援
複雜類型綁定 不支援 支援

使用方式

  1. @Value需要在Bean的成員屬性或者set方法上,逐個設定,和配置檔案進行映射。@Value("${user.username}")
  2. @ConfigurationProperties可以在類上直接配置,屬性會自動映射綁定。
@ConfigurationProperties(prefix = "bsfit.user")
@Component
public class User {

    private String userName;

    private Integer age;
複制代碼           

小結: 如果一個bean下的配置比較多的話,使用@ConfigurationProperties比較友善。

所屬架構

  1. @Value是spring架構的注解,在spring-beans這個工程中。
  2. @ConfigurationProperties注解是Spring Boot實作的一個注解,用于配置檔案對對象屬性的配置。

SPEL

  1. @Value是支援SPEL表達式的,如下:
@Value("#{ T(java.lang.Math).random() * 100.0 }")
 private double randomNumber;
複制代碼           
  1. @ConfigurationProperties不支援SPEL表達式,驗證方式如下:
bsfit.user:
  user-name: ${person.last-name}
  age: #{5*2}
複制代碼           
@ConfigurationProperties(prefix = "bsfit.user")
@Component
public class User {

    private String userName;

    private Integer age;
複制代碼           

輸出結果如下,@ConfigurationProperties無法執行SPEL表達式。

Spring中的@Value和@ConfigurationProperties你是不是用不明白?

小結: @Value在取值方面更加強大,支援SPEL, 同時還能注入URL、檔案等資源

資料校驗

  1. @Value不支援資料校驗
  2. @ConfigurationProperties支援資料校驗,驗證如下:
bsfit.user:
user-name: ${person.last-name}
age: 500
userId: E000001
  sex: boy
複制代碼           
@ConfigurationProperties(prefix = "bsfit.user")
@Component
@ToString
@Validated
public class User {

    private String userName;

    @Max(value = 150, message = "最大值不能超過100歲")
    @Min(value = 10, message = "最大值不能超過10歲")
    private Integer age;

}
複制代碼           

啟動報錯如下:

Spring中的@Value和@ConfigurationProperties你是不是用不明白?

小結: 資料校驗可以用來校驗注入的屬性是否正确、符合規範。而@ConfigurationProperties具備這樣的能力。

松散綁定

松散綁定的意思就是一個屬性在配置檔案中可以有多個屬性名,比如學生類當中的 firstName 屬性,在配置檔案中可以叫 firstName、first-name、first_name 以及 FIRST_NAME。

  1. @Value不支援松散綁定
Spring中的@Value和@ConfigurationProperties你是不是用不明白?
Spring中的@Value和@ConfigurationProperties你是不是用不明白?

執行結果如下,未綁定配置中的值。

Spring中的@Value和@ConfigurationProperties你是不是用不明白?
  1. @ConfigurationProperties支援松散綁定
Spring中的@Value和@ConfigurationProperties你是不是用不明白?

執行結果如下,綁定了配置中的值。

Spring中的@Value和@ConfigurationProperties你是不是用不明白?

小結: @ConfigurationProperties在這友善寬泛,支援松散綁定,這樣會導緻有多個配置都滿足情況,那麼程式會取比對到的第一個綁定到bean的屬性上。

複雜類型綁定

複雜類型綁定是指綁定複雜的資料結果,比如List, Map, List對象等。

  1. @Value不支援複雜類型的綁定
Spring中的@Value和@ConfigurationProperties你是不是用不明白?
Spring中的@Value和@ConfigurationProperties你是不是用不明白?

執行結果如下顯示不支援複雜類型。

Spring中的@Value和@ConfigurationProperties你是不是用不明白?
  1. @ConfigurationProperties支援複雜類型
Spring中的@Value和@ConfigurationProperties你是不是用不明白?

執行結果如下顯示支援複雜類型。

Spring中的@Value和@ConfigurationProperties你是不是用不明白?

小結: @ConfigurationProperties在對複雜類型的支援上比較強大,可以綁定List,Map等,而@Value不行。

總結

上面闡述了兩者的差別,那我們該如何選擇呢,什麼情況下适用@Value,什麼情況下用@ConfigurationProperties?

我的原則是盡量使用@ConfigurationProperties,特别是下面的情況:

  1. 如果Bean的屬性超過2個,并且有可能被多個Bean注入使用,用@ConfigurationProperties更加友善。
  2. 在微服務項目适用配置中心的情況下,盡量使用@ConfigurationProperties,它可以直接動态更新配置。而@Value需要加上@RefreshScope注解。

當然,如果你隻有一個配置注入或者需要用到SPEL,那麼也可以用@Value注解。