Spring Boot中的@ConfigurationProperties使用指南

1.介绍

Spring Boot具有许多有用的功能,包括外部化配置和轻松访问属性文件中定义的属性。

2.简单的Properties

官方文档建议将配置属性隔离到单独的POJO中。

因此,这么做:

@Data
@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {

    private String hostName;
    private int port;
    private String from;

}

@Configuration,以便Spring在应用程序上下文中创建一个Spring bean。

@ConfigurationProperties与所有具有相同前缀的分层属性一起使用效果最佳; 因此,添加了一个mail前缀。

Spring框架使用标准的Java bean设置器,因此我们必须为每个属性声明设置器。

注意:如果不在POJO中使用@Configuration,那么需要在主Spring应用程序类中添加@EnableConfigurationProperties(ConfigProperties.class)来将属性绑定到POJO中:

@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

Spring将自动绑定属性文件中定义的任何属性,该属性文件中带有前缀mail与ConfigProperties类中的字段之一相同。

Spring使用一些宽松的规则来绑定属性。 结果,以下变体都绑定到属性hostName:

mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME

因此,可以使用以下属性文件来设置所有字段:

#Simple properties
mail.hostname=host@mail.com
mail.port=9000
mail.from=mailer@mail.com

2.1. Spring Boot 2.2

从Spring Boot 2.2开始,Spring通过类路径扫描查找并注册@ConfigurationProperties类。 因此,无需使用@Component(和其他元注释,如@Configuration)注释此类,甚至无需使用@EnableConfigurationProperties:

@Data
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
    private String hostName;
    private int port;
    private String from;
}

@SpringBootApplication启用的类路径扫描程序会找到ConfigProperties类,即使没有使用@Component对该类进行注释也是如此。

此外,可以使用@ConfigurationPropertiesScan批注来扫描配置属性类的自定义位置:

@SpringBootApplication
@ConfigurationPropertiesScan("com.example.demo.properties")
public class DemoApplication implements ApplicationRunner {

    @Resource
    private ConfigProperties configProperties;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }


    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(configProperties);
    }
}

这样,Spring将仅在com.example.demo.properties包中查找配置属性类。

3.嵌套Properties

可以在List,Map和类中嵌套属性。

创建一个新的Credentials类用于一些嵌套属性:

@Data
public class Credentials {
    private String authMethod;
    private String username;
    private String password;
}

我们还需要更新ConfigProperties类以使用List,Map和Credentials类:

@Data
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
    private String hostname;
    private int port;
    private String from;
    private List<String> defaultRecipients;
    private Map<String, String> additionalHeaders;
    private Credentials credentials;
}

以下属性文件将设置所有字段:

#Simple properties
mail.hostname=mailer@mail.com
mail.port=9000
mail.from=mailer@mail.com

#List properties
mail.defaultRecipients[0]=admin@mail.com
mail.defaultRecipients[1]=owner@mail.com

#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true

#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1

打印结果:

ConfigProperties(host=null, port=9000, from=mailer@mail.com, defaultRecipients=[admin@mail.com, owner@mail.com], additionalHeaders={redelivery=true, secure=true}, credentials=Credentials(authMethod=SHA1, username=john, password=password))

4.在@Bean方法上使用@ConfigurationProperties

还可以在@Bean注释的方法上使用@ConfigurationProperties注释。

当要将属性绑定到控制范围之外的第三方组件时,此方法可能特别有用。

创建一个简单的Item类,将在下一个示例中使用它:

@Configuration
public class ConfigPropertiesV2 {
    @Bean
    @ConfigurationProperties(prefix = "item")
    public Item item() {
        return new Item();
    }
}

item.name=apple
item.size=100

任何带有项目前缀的属性都将映射到Spring上下文管理的Item实例。

5.Properties校验

引入依赖

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.16.Final</version>
        </dependency>

@ConfigurationProperties使用JSR-303格式提供属性验证。

@Data
@ConfigurationProperties(prefix = "mail")
@Configuration
@Validated
public class ConfigProperties {
    @NotBlank
    private String hostname;
    @Min(1025)
    @Max(65536)
    private int port;
    @Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
    private String from;
    private List<String> defaultRecipients;
    private Map<String, String> additionalHeaders;
    private Credentials credentials;
}

这有助于减少代码中的if-else条件,并使它看起来更加简洁明了。

如果这些验证中的任何一个失败,则主应用程序将无法以IllegalStateException启动。

Hibernate Validation框架使用标准的Java bean的getter和setter,因此对每个属性声明getter和setter很重要。

6.属性转化

@ConfigurationProperties支持将属性绑定到其对应bean的多种类型的转换。

6.1. Duration

从查看将属性转换为Duration对象开始。

在这里,有两个类型为Duration的字段:

@Data
@ConfigurationProperties(prefix = "conversion")
@Configuration
public class PropertyConversion {

    private Duration timeInDefaultUnit;
    private Duration timeInNano;
}

properties文件

conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns

结果,字段timeInDefaultUnit的值为10毫秒,而timeInNano字段的值为9纳秒。

支持的单位分别为ns,us,ms,s,m,h和d,分别为纳秒,微秒,毫秒,秒,分钟,小时和天。

默认单位是毫秒,这意味着如果我们不指定数值旁边的单位,Spring会将值转换为毫秒。

也可以使用@DurationUnit覆盖默认单位:

@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;
conversion.timeInDays=2

6.2. DataSize

同样,Spring Boot @ConfigurationProperties支持DataSize类型转换。

    private DataSize sizeInDefaultUnit;

    private DataSize sizeInGB;

    @DataSizeUnit(DataUnit.TERABYTES)
    private DataSize sizeInTB;

这些是相应的属性:

conversion.sizeInDefaultUnit=300
conversion.sizeInGB=2GB
conversion.sizeInTB=4

在这种情况下,sizeInDefaultUnit的值为300个字节,因为默认单位为字节

支持的单位是B,KB,MB,GB和TB。 还可以使用@DataSizeUnit覆盖默认单位。

在这里插入图片描述

### 解决@ConfigurationProperties未配置的问题 #### 正确配置@ConfigurationProperties注解的方法 为了使`@ConfigurationProperties`正常工作,需遵循特定的设置流程。首先,在引入此功能前,确认项目的pom.xml已包含`spring-boot-configuration-processor`依赖项,这有助于编译期间处理元数据并提供自动完成支持[^3]。 其次,创建用于绑定属性的Java类,并在其上标注`@ConfigurationProperties(prefix="your.prefix")`,指定要映射到该对象实例上的键前缀。例如: ```java import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "spring.datasource") public class DataSourceProperties { private String url; // Getters and Setters } ``` 还需注意的是,如果希望这些自定义配置能够被Spring容器识别,则应在启动类或任意配置类中标记`@EnableConfigurationProperties(DataSourceProperties.class)`来激活它们[^2]。 最后,确保application.yml或application.properties中的相应条目格式正确无误,即key和value之间应保留至少一个空格[^5]。 #### 常见问题排查指南 1. **缺少处理器依赖** 若遇到无法解析`@ConfigurationProperties`的情况,可能是由于缺失了必要的构建工具插件。对于Maven项目来说,应该核查是否存在如下声明: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> ``` 2. **未能启用特性开关** 即便已经添加了上述依赖,仍可能因为忘记开启特性的缘故而失效。此时应当检查是否有通过`@EnableConfigurationProperties`显式启用了目标bean的支持。 3. **错误的应用程序上下文扫描路径** 当应用程序包结构较为复杂时,可能会出现组件扫描不到预期位置的现象。建议调整主应用类的位置至顶层包下,以便于全面覆盖所有子包内的候选者。 4. **不匹配的数据类型转换失败** `@ConfigurationProperties`会尝试依据字段定义自动执行字符串与其他基本类型的互转操作。然而一旦发生异常(比如日期格式不符),则可能导致初始化过程抛出异常。因此务必保证外部传入值与内部接收变量之间的兼容性良好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值