概述
相信大家在在各自的項目中都使用過@Value和@ConfigurationProperties兩個注解,他們可以自動從我們的配置檔案中擷取配置資訊,那他們之間有什麼差別呢,我們該優先選擇哪種方式來讀取配置呢?
差別
兩個注解的使用方式和源碼解析可以參考下面的兩個文章,本篇我們重點關注在他們的差別上。
@Value的使用: 一文深入了解Spring中的@Value注解
@ConfigurationProperties的使用: 一文深入了解ConfigurationProperties注解
比較項 | @Value | @ConfigurationProperties |
使用方式 | 需要一個個指定 | 能夠批量地注入配置檔案中的屬性 |
所屬架構 | Spring | Spring Boot |
SPEL | 支援 | 不支援 |
JSR303資料校驗 | 不支援 | 支援 |
松散綁定 | 不支援 | 支援 |
複雜類型綁定 | 不支援 | 支援 |
使用方式
- @Value需要在Bean的成員屬性或者set方法上,逐個設定,和配置檔案進行映射。@Value("${user.username}")
- @ConfigurationProperties可以在類上直接配置,屬性會自動映射綁定。
@ConfigurationProperties(prefix = "bsfit.user")
@Component
public class User {
private String userName;
private Integer age;
複制代碼
小結: 如果一個bean下的配置比較多的話,使用@ConfigurationProperties比較友善。
所屬架構
- @Value是spring架構的注解,在spring-beans這個工程中。
- @ConfigurationProperties注解是Spring Boot實作的一個注解,用于配置檔案對對象屬性的配置。
SPEL
- @Value是支援SPEL表達式的,如下:
@Value("#{ T(java.lang.Math).random() * 100.0 }")
private double randomNumber;
複制代碼
- @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表達式。
小結: @Value在取值方面更加強大,支援SPEL, 同時還能注入URL、檔案等資源
資料校驗
- @Value不支援資料校驗
- @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;
}
複制代碼
啟動報錯如下:
小結: 資料校驗可以用來校驗注入的屬性是否正确、符合規範。而@ConfigurationProperties具備這樣的能力。
松散綁定
松散綁定的意思就是一個屬性在配置檔案中可以有多個屬性名,比如學生類當中的 firstName 屬性,在配置檔案中可以叫 firstName、first-name、first_name 以及 FIRST_NAME。
- @Value不支援松散綁定
執行結果如下,未綁定配置中的值。
- @ConfigurationProperties支援松散綁定
執行結果如下,綁定了配置中的值。
小結: @ConfigurationProperties在這友善寬泛,支援松散綁定,這樣會導緻有多個配置都滿足情況,那麼程式會取比對到的第一個綁定到bean的屬性上。
複雜類型綁定
複雜類型綁定是指綁定複雜的資料結果,比如List, Map, List對象等。
- @Value不支援複雜類型的綁定
執行結果如下顯示不支援複雜類型。
- @ConfigurationProperties支援複雜類型
執行結果如下顯示支援複雜類型。
小結: @ConfigurationProperties在對複雜類型的支援上比較強大,可以綁定List,Map等,而@Value不行。
總結
上面闡述了兩者的差別,那我們該如何選擇呢,什麼情況下适用@Value,什麼情況下用@ConfigurationProperties?
我的原則是盡量使用@ConfigurationProperties,特别是下面的情況:
- 如果Bean的屬性超過2個,并且有可能被多個Bean注入使用,用@ConfigurationProperties更加友善。
- 在微服務項目适用配置中心的情況下,盡量使用@ConfigurationProperties,它可以直接動态更新配置。而@Value需要加上@RefreshScope注解。
當然,如果你隻有一個配置注入或者需要用到SPEL,那麼也可以用@Value注解。