在 Spring Boot 中,@ConfigurationProperties 注解的核心作用是将配置文件(如 application.properties /application.yml)中的属性批量绑定到 Java 实体类,避免手动通过 @Value 逐个注入属性,尤其适合处理多属性、层级化的配置场景(如数据库连接、第三方 API 配置等)。
下面分 基础使用步骤、进阶场景(层级配置、松散绑定、校验)、常见问题 三部分,详细讲解其用法:
一、基础使用步骤(核心流程)
步骤 1:创建配置属性实体类
定义一个 Java 类,用 @ConfigurationProperties 指定配置文件中的属性前缀(如 spring.datasource、custom.oss),并提供属性的 getter/setter 方法(Spring 需通过 setter 注入值)。
示例:绑定 OSS 存储配置
假设配置文件中需要配置阿里云 OSS 的相关信息,实体类如下:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
// 1. 标注注解:prefix 指定配置文件中的属性前缀(必须与配置文件一致)
@ConfigurationProperties(prefix = "custom.oss")
// 2. 注册为 Spring Bean(三种方式选一种即可,下文详细说明)
@Component
public class OssProperties {
// 配置文件中的属性名:custom.oss.endpoint
private String endpoint;
// 配置文件中的属性名:custom.oss.access-key
private String accessKey;
// 配置文件中的属性名:custom.oss.secret-key
private String secretKey;
// 配置文件中的属性名:custom.oss.bucket-name
private String bucketName;
// 3. 必须提供 getter 和 setter 方法(Spring 自动注入值)
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
}
步骤 2:在配置文件中添加对应属性
在 application.yml(推荐,层级清晰)或 application.properties 中,添加与 prefix 匹配的属性:
方式 1:application.yml(推荐)
custom:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
access-key: LTAI4Gxxxxxxx
secret-key: 8Zxxxxxxxxxxxxxx
bucket-name: my-test-bucket
方式 2:application.properties
# 前缀 + 属性名,用 "." 分隔
custom.oss.endpoint=https://oss-cn-beijing.aliyuncs.com
custom.oss.access-key=LTAI4Gxxxxxxx
custom.oss.secret-key=8Zxxxxxxxxxxxxxx
custom.oss.bucket-name=my-test-bucket
步骤 3:注册配置属性类(3 种方式)
@ConfigurationProperties 本身不会将类注册为 Spring Bean,需配合以下方式之一让 Spring 扫描到该类:
方式 1:直接在实体类上加 @Component(简单场景)
如步骤 1 中的代码,直接在 OssProperties 上添加 @Component(或 @Configuration),Spring 会自动扫描并注入属性(需确保该类在 @SpringBootApplication 的扫描范围内,即包路径一致或子路径)。
方式 2:在配置类中用 @EnableConfigurationProperties 激活(推荐,解耦)
如果不想在实体类上加 @Component(例如实体类在第三方包中,无法修改),可在任意 @Configuration 类(如启动类)上添加 @EnableConfigurationProperties,指定要激活的配置属性类:
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
// 激活 OssProperties,Spring 会自动将其注册为 Bean
@EnableConfigurationProperties(OssProperties.class)
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
方式 3:在配置类中用 @Bean 手动注册(灵活控制)
通过 @Bean 方法手动创建配置属性类的实例,适用于需要自定义初始化逻辑的场景:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OssConfig {
// 手动注册 OssProperties 为 Bean,并绑定配置
@Bean
@ConfigurationProperties(prefix = "custom.oss")
public OssProperties ossProperties() {
// 可在这里添加自定义初始化逻辑
return new OssProperties();
}
}
步骤 4:使用配置属性(注入 Bean 即可)
在业务类(如 Service、Controller)中,通过 @Autowired 注入配置属性类,直接使用绑定后的属性:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OssService {
// 注入配置属性类(Spring 已自动绑定配置文件中的值)
@Autowired
private OssProperties ossProperties;
public void uploadFile() {
// 直接使用配置属性
String endpoint = ossProperties.getEndpoint();
String accessKey = ossProperties.getAccessKey();
System.out.println("OSS 上传地址:" + endpoint);
System.out.println("AccessKey:" + accessKey);
// 后续业务逻辑...
}
}
二、进阶场景(实用功能)
1. 层级化配置(嵌套属性)
如果配置存在多层嵌套(如 custom.oss.cdn.domain),可通过嵌套内部类或独立类实现绑定。
示例:嵌套配置
(1)配置文件(application.yml)
custom:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
access-key: LTAI4Gxxxxxxx
secret-key: 8Zxxxxxxxxxxxxxx
bucket-name: my-test-bucket
# 嵌套属性:CDN 相关配置
cdn:
domain: https://cdn.my-bucket.com
expire: 3600 # 链接有效期(秒)
(2)配置属性类(嵌套内部类)
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "custom.oss")
@Component
public class OssProperties {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucketName;
// 嵌套内部类:对应 custom.oss.cdn
private Cdn cdn;
// getter/setter(包括 Cdn 的 getter/setter)
public String getEndpoint() { return endpoint; }
public void setEndpoint(String endpoint) { this.endpoint = endpoint; }
// ... 其他属性的 getter/setter
public Cdn getCdn() { return cdn; }
public void setCdn(Cdn cdn) { this.cdn = cdn; }
// 嵌套内部类(必须是 static,否则无法绑定)
public static class Cdn {
private String domain;
private Integer expire;
// getter/setter
public String getDomain() { return domain; }
public void setDomain(String domain) { this.domain = domain; }
public Integer getExpire() { return expire; }
public void setExpire(Integer expire) { this.expire = expire; }
}
}
(3)使用嵌套属性
@Service
public class OssService {
@Autowired
private OssProperties ossProperties;
public void getCdnInfo() {
// 访问嵌套属性:custom.oss.cdn.domain
String cdnDomain = ossProperties.getCdn().getDomain();
Integer cdnExpire = ossProperties.getCdn().getExpire();
System.out.println("CDN 域名:" + cdnDomain + ",有效期:" + cdnExpire + "秒");
}
}
2. 松散绑定(属性名不严格匹配)
@ConfigurationProperties 支持松散的属性名绑定,即配置文件中的属性名格式与 Java 实体类的属性名格式可以不一致,Spring 会自动匹配。
支持的绑定规则:
| Java 实体类属性名(驼峰式) | 配置文件中允许的格式 |
|---|---|
accessKey | access-key(中划线,推荐.yml)、access_key(下划线)、accessKey(驼峰)、ACCESS_KEY(全大写) |
bucketName | bucket-name、bucket_name、bucketName、BUCKET_NAME |
示例:
Java 类属性:private String accessKey; 配置文件中可写:
custom:
oss:
access-key: LTAI4Gxxxxxxx # 推荐(yml 风格)
# 或 access_key: LTAI4Gxxxxxxx
# 或 accessKey: LTAI4Gxxxxxxx
# 或 ACCESS_KEY: LTAI4Gxxxxxxx
3. 配置属性校验(避免非法值)
通过 JSR-380 注解(如 @NotNull、@Min、@Pattern)对配置属性进行校验,确保配置值合法。需先添加校验依赖,再在实体类上添加校验注解。
步骤 1:添加校验依赖
Maven(pom.xml):
<!-- 配置属性校验依赖(Spring Boot 2.x+ 已包含,若缺失则添加) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-starter-validation'
步骤 2:在实体类上添加校验注解
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
// 1. 添加 @Validated 开启校验(必须)
@Validated
@ConfigurationProperties(prefix = "custom.oss")
@Component
public class OssProperties {
// 非空校验:配置文件中必须存在 custom.oss.endpoint
@NotBlank(message = "OSS endpoint 不能为空")
private String endpoint;
@NotBlank(message = "accessKey 不能为空")
private String accessKey;
@NotBlank(message = "secretKey 不能为空")
private String secretKey;
@NotBlank(message = "bucketName 不能为空")
private String bucketName;
// 嵌套属性校验(内部类也需加 @Valid)
@Valid
private Cdn cdn;
// getter/setter...
public static class Cdn {
@NotBlank(message = "CDN domain 不能为空")
private String domain;
// 正数校验:expire 必须大于 0
@NotNull(message = "CDN expire 不能为空")
@Positive(message = "CDN expire 必须为正数")
private Integer expire;
// getter/setter...
}
}
效果:
若配置文件中缺失 custom.oss.endpoint 或 cdn.expire 为负数,应用启动时会直接抛出 BindValidationException,明确提示错误原因,避免运行时异常。
4. 配置默认值(避免配置缺失)
可在 Java 实体类的属性中直接设置默认值,当配置文件中未指定该属性时,会使用默认值:
@ConfigurationProperties(prefix = "custom.oss")
@Component
public class OssProperties {
// 默认值:若配置文件中未写 custom.oss.endpoint,则使用该值
private String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
private String accessKey;
private String secretKey;
// 嵌套属性默认值
private Cdn cdn = new Cdn(); // 初始化嵌套类
// getter/setter...
public static class Cdn {
private String domain = "https://default-cdn.com";
private Integer expire = 7200; // 默认有效期 2 小时
// getter/setter...
}
}
三、常见问题与注意事项
1. 配置属性注入失败?(排查步骤)
- 检查配置文件中的
prefix 与属性名是否匹配(如 custom.oss 对应 custom.oss.endpoint); - 确保配置属性类已注册为 Spring Bean(加
@Component 或通过 @EnableConfigurationProperties 激活); - 确保属性提供了
getter/setter 方法(Spring 通过 setter 注入值,无 setter 则无法绑定); - 检查配置文件是否在正确路径下(默认是
src/main/resources/application.yml/application.properties); - 若使用
@EnableConfigurationProperties,确保该注解加在 @Configuration 类(如启动类)上。
2. 区分 @ConfigurationProperties 与 @Value
| 特性 | @ConfigurationProperties | @Value |
|---|---|---|
| 用途 | 批量绑定多属性、层级属性 | 单个属性注入 |
| 松散绑定 | 支持(如 access-key 绑定 accessKey) | 不支持(需严格匹配属性名) |
| 类型转换 | 自动转换(如 String → Integer) | 需手动指定转换器(如 @Value("${xxx:#{T(Integer).valueOf('10')}}")) |
| 校验支持 | 支持(配合 @Validated) | 不支持(需手动校验) |
| 适用场景 | 复杂配置(数据库、第三方 API) | 简单单个属性(如端口、环境变量) |
3. 读取自定义配置文件(非 application.yml)
默认情况下,@ConfigurationProperties 读取 application.yml/application.properties。若需读取自定义文件(如 src/main/resources/config/oss-config.yml),可配合 @PropertySource 注解(注意:@PropertySource 默认不支持 YAML 文件,需额外配置):
步骤 1:添加 YAML 解析器(支持 @PropertySource 读取 YAML)
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import java.io.IOException;
import java.util.List;
import org.springframework.core.env.PropertySource;
// 自定义 PropertySourceFactory,支持 YAML 文件
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource());
return sources.get(0);
}
}
步骤 2:在配置属性类上指定自定义文件
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "custom.oss")
@Component
// 指定自定义 YAML 文件,使用上面的 YamlPropertySourceFactory
@PropertySource(value = "classpath:config/oss-config.yml", factory = YamlPropertySourceFactory.class)
public class OssProperties {
// 属性 + getter/setter...
}
四、总结
@ConfigurationProperties 是 Spring Boot 中管理配置的核心注解,核心优势是批量绑定、层级支持、松散绑定、校验能力,适合处理复杂配置场景。
使用流程可简化为:
- 定义实体类 +
@ConfigurationProperties(prefix = "xxx"); - 注册为 Spring Bean(
@Component 或 @EnableConfigurationProperties); - 配置文件中添加对应属性;
- 业务类中注入实体类使用。
掌握其进阶功能(校验、默认值、嵌套配置)可大幅提升配置管理的规范性和稳定性,避免运行时配置相关的 Bug。