SpringBoot整體讀取多個配置屬性及其相關操作方法
上篇文章講到使用@Value注解每次只能讀取一個配置屬性,若要整體讀取多個屬性,或者讀取具有某種結構關系的一組屬性可使用@ConfigurationProperties注解來處理。
@ConfigurationProperties注解的兩種用法:
- 修飾屬性處理類:當@ConfigurationProperties修飾的類被部署為容器中的Bean時,改注解指定的屬性會被注入該Bean的屬性。因此,@ConfigurationProperties修飾的類稱為“屬性處理類”。
- 修飾@Bean注解修飾的方法:使用@Bean修飾的方法蔣會配置一個容器中的Bean,而@ConfigurationProperties指定的屬性會被注入該Bean的屬性。
看不懂沒關系,下面會有代碼示例。
在使用@ConfigurationProperties時可指定如下屬性:
- prefix(或value):指定要加載的屬性的前綴
- ignoreInvaildFields():指定是否忽略無效屬性值。比如處理類定義了某個字段的類型是Integer,但在配置文件中的值是abc,這就是無效值。
- ignoreUnknowFields():指定是否忽略未知的字段值。如果在配置文件中配置的屬性比處理類需要的屬性更多,那么多出來的屬性就是未知屬性。
使用屬性處理類獲取配置屬性
直接來看代碼示例:
\resources\application.properties文件內容:
org.crazyit.enabled=true org.crazyit.name=Crazy Java org.crazyit.remoteAddress=192.168.1.188 org.crazyit.item.brand=Tesla org.crazyit.item.comments=Good, Excellent
(使用IDEA開發(fā)屬性處理類時,添加spring-boot-configuration-processor依賴,IDEA會提供“代碼補全”功能。
<!-- 添加該依賴后IDEA可以提供自動補全功能 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
)
SpringBoot不會自動啟用@ConfigurationProperties注解,啟用該注解有如下方式:
- 為@ConfigurationProperties注解修飾的類加@Component注解
- 為@ConfigurationProperties注解修飾的類顯式配置成容器中的bean
- 使用@EnableConfigurationProperties注解,該注解顯式指定一個或多個屬性處理類,SpringBoot會啟用這些屬性處理類上的@ConfigurationProperties注解
- 使用@ConfigurationPropertiesScan注解,該注解指定一個或多個包及其子包下所有帶@ConfigurationProperties注解的類
@ConfigurationProperties注解修飾的屬性處理類代碼:
// 指定讀取以org.crazyit.*開頭的屬性
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
@Component
public class CrazyitProperties
{
// 指定同名的實例變量和setter方法。SpringBoot會通過反射調用setter方法來完成屬性值注入
private boolean enabled;
private String name;
private InetAddress remoteAddress;
private final Item item = new Item();
// 省略getter\setter
public static class Item
{
private String brand;
private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
// 省略getter\setter
}
}控制器類代碼示例:
@RestController
public class HelloController
{
private final CrazyitProperties crazyitProperties;
// 依賴注入CrazyitProperties屬性處理Bean
@Autowired
public HelloController(CrazyitProperties crazyitProperties)
{
this.crazyitProperties = crazyitProperties;
}
@GetMapping
public CrazyitProperties hello()
{
return crazyitProperties;
}
}運行結果:

屬性處理類也支持使用構造器完成屬性值注入,但是要額外使用@ConstructorBinding修飾用于執(zhí)行構造注入的構造器。注意:使用構造器注入,必須使用@EnableConfigurationProperties或者@ConfigurationPropertiesScan注解來啟用@ConfigurationProperties注解。
屬性處理類示例:
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
public class CrazyitProperties
{
private boolean enabled;
private String name;
private InetAddress remoteAddress;
private final Item item;
@ConstructorBinding
public CrazyitProperties(boolean enabled, String name, InetAddress remoteAddress, Item item)
{
this.enabled = enabled;
this.name = name;
this.remoteAddress = remoteAddress;
this.item = item;
}
// 省略getter\setter
public static class Item
{
private String brand;
private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
// 省略getter\setter
}
}application.yml
org:
crazyit:
enabled: true
name: 哈利波特
remote-address: 192.168.1.188
item:
brand: Apple
comments:
- Good
- Excellent上面配置的屬性為org.crazyit.remote-address與CrazyitProperties類中定義的remoteAddress屬性不完全相同,SpringBoot能成功注入嗎?
答案是肯定的,因為SpringBoot支持寬松綁定(Relaxed Binding)。它不要求配置的屬性名和屬性處理類中的屬性名完全相同。
寬松綁定的四種情況(這4種情況都能完成注入):
- org.crazyit.remote-address
- org.crazyit. remoteAddress
- org.crazyit. remote_address
- ORG_CRAZYIT_REMOTEADDRESS
在*.properties和 *.yml文件中配置List類型的屬性有較小的區(qū)別:
- 在*.properties文件中配置List有2種方式:英文逗號隔開多個值;用標準方括號
- 在 *.yml文件中配置List有2種方式:英文逗號隔開多個值;用短橫線開頭(例子所示)
因此,*.properties和 *.yml文件中,都可以用英文逗號隔開多個值來構建List。
App.java示例
@SpringBootApplication
// 指定掃描org.crazyit.app.config包及其子包下的@ConfigurationProperties注解修飾的類
@ConfigurationPropertiesScan("org.crazyit.app.config")
public class App
{
public static void main(String[] args)
{
// 創(chuàng)建Spring容器、運行Spring Boot應用
SpringApplication.run(App.class, args);
}
}為容器中的bean注入配置屬性
@ConfigurationProperties注解除了可修飾類,還可修飾@Bean注解修飾的方法。
代碼示例:Book類
public class Book
{
private String title;
private double price;
private String author;
private List<String> keywords;
// 省略getter、setter
}代碼示例:配置類
@Configuration
public class MyConfig
{
@Bean
// @ConfigurationProperties注解會驅動Spring自動調用該Bean的setter方法
@ConfigurationProperties("fkjava.book")
public Book book()
{
return new Book();
}
}代碼示例:application.yml
fkjava:
book:
title: "美語音標"
price: 128
author: "賴世雄"
keywords:
- 英語
- 音標代碼示例:控制器類
@RestController
public class HelloController
{
private final Book book;
// 通過構造器注入Book對象
@Autowired
public HelloController(Book book)
{
this.book = book;
}
@GetMapping
public Book hello()
{
return book;
}
}運行結果:

@Value和 @ConfigurationProperties的對比
| 特征 | @ConfigurationProperties | @Value |
|---|---|---|
| 注入的屬性個數(shù) | 批量 | 單個 |
| 寬松綁定 | 支持 | 部分支持 |
| SpEL | 不支持 | 支持 |
| 元數(shù)據(jù)支持 | 支持 | 不支持 |
屬性轉換
SpringBoot內置了常用的類型轉換機制,如果在轉換失敗,則應用啟動會失敗,并拋出異常。如果要忽略轉換失敗的屬性,可將@ConfigurationProperties注解的ignoreInvaildFields屬性設為true(默認是false)。
SpringBoot可自動轉換如下類型:Duration、Period、DataSize,并支持為屬性值指定單位。
- Duration類型可指定的單位:ns納秒、μs微妙、ms毫秒、s秒、m分鐘、h小時、d天。
- Period類型可指定的單位:y年、m月、w星期、d天。(例如配置1y3d,代表1年3天)。
- DataSize類型可指定的單位:B字節(jié)、KB千字節(jié)、MB兆字節(jié)、GB吉字節(jié)、TB太字節(jié)
代碼示例:屬性處理類
// 指定讀取以org.crazyit.*開頭的屬性
@ConfigurationProperties(prefix = "org.crazyit")
@Component
public class CrazyitProperties
{
private Duration timeout;
// @DurationUnit注解指定默認的時間單位
@DurationUnit(ChronoUnit.SECONDS)
private Duration lastTime;
private Period runPeriod;
// @DataSizeUnit注解指定默認的數(shù)據(jù)單位
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize maxSize;
// 省略getter、setter
}代碼示例:application.properties
org.crazyit.timeout=30000 # 默認單位是秒 org.crazyit.last-time=45 org.crazyit.run-period=2m5d org.crazyit.max-size=2
代碼示例:控制器類
@RestController
public class HelloController
{
private final CrazyitProperties crazyitProperties;
// 依賴注入CrazyitProperties屬性處理Bean
@Autowired
public HelloController(CrazyitProperties crazyitProperties)
{
this.crazyitProperties = crazyitProperties;
}
@GetMapping
public Map<String, Object> hello()
{
System.out.println(crazyitProperties.getMaxSize().toKilobytes());
return Map.of("props", crazyitProperties,
"maxSize", crazyitProperties.getMaxSize().toKilobytes());
}
}運行結果:

校驗@ConfigurationProperties
只要為屬性處理類添加@Validated注解,并使用JSR303的校驗注解修飾需要校驗的示例變量,SpringBoot會自動校驗配置文件中的屬性值。如果某個屬性校驗不通過,應用會啟動失敗,并用FailureAnalyzer顯式校驗錯誤。
如果屬性處理類包含復合類型的屬性,且要對復合類型的子屬性進行校驗,則應為該復合類型的屬性添加@Valid注解。
@ConfigurationProperties校驗基于JSR303,因此必須添加JSR303依賴,spring-boot-starter-validation依賴庫包含了JSR303的依賴,因此要在pom文件中添加以下依賴
<!-- 添加Spring Boot Validation依賴庫 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
屬性處理類示例:
// 指定讀取以org.crazyit.*開頭的屬性
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
@Component
@Validated
public class CrazyitProperties
{
@NotEmpty
private String name;
@Range(max = 150, min=90, message = "價格必須位于90~150之間")
private double price;
@Pattern(regexp = "[1][3-8][0-9]{9}", message = "必須輸入有效的手機號")
private String mobile;
@Valid
private final Item item = new Item();
// 省略getter setter
public static class Item
{
@Length(min=5, max=10, message = "品牌名長度必須在5到10個字符")
private String brand;
@Size(min = 1, message = "comments至少包含一個元素")
private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
// 省略getter、setter
}
}代碼示例:application.properties
org.crazyit.name=Crazy Java org.crazyit.price=89 org.crazyit.mobile=13334444 org.crazyit.item.brand=Apple org.crazyit.item.comments=Great, Excellent
運行結果:

對于使用@ConfigurationProperties修飾@Bean方法的情況,同樣可對配置屬性進行校驗,主要為@Bean方法添加@Validated注解即可。
到此這篇關于SpringBoot整體讀取多個配置屬性及其相關操作的文章就介紹到這了,更多相關SpringBoot讀取多個配置屬性內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- springboot使用@ConfigurationProperties實現(xiàn)自動綁定配置參數(shù)屬性
- SpringBoot3讀取配置文件application.properties屬性值的幾種方式
- SpringBoot高級配置之臨時屬性、配置文件、日志、多環(huán)境配置詳解
- SpringBoot測試配置屬性與web啟動環(huán)境超詳細圖解
- SpringBoot配置文件中密碼屬性加密的實現(xiàn)
- springboot配置文件屬性變量引用方式${}和@@用法及區(qū)別說明
- springboot 自定義配置Boolean屬性不生效的解決
- SpringBoot從配置文件中獲取屬性的四種方法總結
相關文章
Java中static和static?final的區(qū)別詳解
這篇文章主要介紹了Java中static和static?final的區(qū)別詳解,開發(fā)時我們經(jīng)常用到static以及static?final來修飾我們的字段變量,那么他們到底有什么區(qū)別呢?其實他們的區(qū)別可以用使用字節(jié)碼文件來解析,需要的朋友可以參考下2023-10-10
Redis中String字符串和sdshdr結構體超詳細講解
這篇文章主要介紹了Redis中String字符串和sdshdr結構體,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2023-04-04
你知道在Java中Integer和int的這些區(qū)別嗎?
最近面試,突然被問道,說一下Integer和int的區(qū)別.額…可能平時就知道寫一些業(yè)務代碼,包括面試的一些Spring源碼等,對于這種特別基礎的反而忽略了,導致面試的時候突然被問到反而不知道怎么回答了.哎,還是乖乖再看看底層基礎,順帶記錄一下把 ,需要的朋友可以參考下2021-06-06
springmvc級聯(lián)屬性處理無法轉換異常問題解決
這篇文章主要介紹了springmvc級聯(lián)屬性處理無法轉換異常問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12
SpringBoot連接Nacos集群報400問題及完美解決方法
這篇文章主要介紹了解決SpringBoot連接Nacos集群報400問題?,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02

