1. 简介
Spring Boot 提供了强大的外部化配置功能,能轻松处理属性文件中的配置项。本文将深入探讨 @ConfigurationProperties
注解的核心用法和高级特性。
2. 环境准备
首先在 pom.xml
中添加标准依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<relativePath/>
</parent>
为启用属性校验功能,添加验证依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
⚠️ 更多 Hibernate Validator 细节可参考官方文档
3. 基础属性绑定
最佳实践是将配置属性隔离到独立 POJO 中:
@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// 标准 getter/setter
}
关键点说明:
@Configuration
使 Spring 创建 Beanprefix = "mail"
指定公共前缀- 必须提供标准 setter 方法
✅ 如果不使用
@Configuration
,需在主类添加@EnableConfigurationProperties(ConfigProperties.class)
Spring 支持灵活的属性名绑定规则:
mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME
对应配置文件示例:
# 基础属性
mail.hostName=smtp.example.com
mail.port=9000
mail.from=admin@example.com
3.1. Spring Boot 2.2 新特性
从 2.2 版本开始,Spring 通过类路径扫描自动注册 @ConfigurationProperties
类:
@ConfigurationProperties(prefix = "mail")
@ConfigurationPropertiesScan
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// 标准 getter/setter
}
✅ 无需再添加
@Component
或@EnableConfigurationProperties
自定义扫描路径示例:
@SpringBootApplication
@ConfigurationPropertiesScan("com.example.config")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4. 嵌套属性处理
支持 List
、Map
和自定义类的嵌套结构:
public class Credentials {
private String authMethod;
private String username;
private String password;
// 标准 getter/setter
}
更新主配置类:
public class ConfigProperties {
private String hostname;
private int port;
private String from;
private List<String> defaultRecipients;
private Map<String, String> additionalHeaders;
private Credentials credentials;
// 标准 getter/setter
}
对应配置文件:
# 基础属性
mail.hostName=smtp.example.com
mail.port=9000
mail.from=admin@example.com
# List 属性
mail.defaultRecipients[0]=dev@example.com
mail.defaultRecipients[1]=ops@example.com
# Map 属性
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true
# 对象属性
mail.credentials.username=john
mail.credentials.password=secret
mail.credentials.authMethod=SHA1
5. 在 @Bean 方法上使用
适用于绑定第三方组件的属性:
public class Item {
private String name;
private int size;
// 标准 getter/setter
}
配置类示例:
@Configuration
public class ConfigProperties {
@Bean
@ConfigurationProperties(prefix = "item")
public Item item() {
return new Item();
}
}
所有
item
前缀的属性将自动绑定到该 Bean
6. 属性校验
通过 JSR-380 规范实现强大校验能力:
@NotBlank
private String hostName;
@Length(max = 4, min = 1)
private String authMethod;
@Min(1025)
@Max(65536)
private int port;
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;
❌ 校验失败将导致应用启动失败并抛出
IllegalStateException
⚠️ 必须提供标准 getter/setter 才能使校验生效
7. 属性类型转换
7.1. Duration 类型
private Duration timeInDefaultUnit;
private Duration timeInNano;
@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;
配置示例:
conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns
conversion.timeInDays=2
✅ 支持单位:
ns, us, ms, s, m, h, d
,默认毫秒
7.2. DataSize 类型
private DataSize sizeInDefaultUnit;
private DataSize sizeInGB;
@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;
配置示例:
conversion.sizeInDefaultUnit=300
conversion.sizeInGB=2GB
conversion.sizeInTB=4
✅ 支持单位:
B, KB, MB, GB, TB
,默认字节
7.3. 自定义转换器
实现 Converter
接口处理特殊类型:
public class Employee {
private String name;
private double salary;
}
转换器实现:
@Component
@ConfigurationPropertiesBinding
public class EmployeeConverter implements Converter<String, Employee> {
@Override
public Employee convert(String from) {
String[] data = from.split(",");
return new Employee(data[0], Double.parseDouble(data[1]));
}
}
配置示例:
conversion.employee=john,2000
8. 不可变属性绑定
Spring Boot 2.2+ 支持构造器绑定实现不可变配置:
@ConfigurationProperties(prefix = "mail.credentials")
public class ImmutableCredentials {
private final String authMethod;
private final String username;
private final String password;
@ConstructorBinding
public ImmutableCredentials(String authMethod, String username, String password) {
this.authMethod = authMethod;
this.username = username;
this.password = password;
}
// 省略其他构造器和 getter
}
⚠️ 所有字段必须是 final,且无 setter 方法
✅ 需通过
@EnableConfigurationProperties
或@ConfigurationPropertiesScan
显式启用
9. Java 16 Record 支持
Record 类型天然适合配置属性场景:
@ConstructorBinding
@ConfigurationProperties(prefix = "mail.credentials")
public record ImmutableCredentials(
String authMethod,
String username,
String password
) {}
✅ Spring Boot 2.6+ 对单构造器 Record 可省略
@ConstructorBinding
10. 总结
@ConfigurationProperties
提供了:
- ✅ 灵活的属性绑定机制
- ✅ 强大的类型转换能力
- ✅ 完整的 JSR-380 校验支持
- ✅ 不可变配置实现方案
- ✅ Java Record 原生支持
完整示例代码请参考 GitHub 仓库