SpringBoot @ConfigurationProperties作用及属性讲解

关于@ConfigurationProperties曾提过一个issue,涉及SpringBoot 2.2.1之前版本
Setting ignoreInvalidFields=true on @ConfigurationProperties causes unknown fields to be ignored as well

@ConfigurationProperties主要作用就是将prefix属性指定的前缀配置项的值绑定到这个Bean上,默认情况下需要和@Component或者@Configuration一起使用才能生效.

实现原理参见另一篇博客: @EnableConfigurationProperties @ConfigurationProperties @ConfigurationPropertiesScan

本文主要讲解@ConfigurationProperties注解中的几个属性作用. 及两种使用方式:

  1. 使用在类上
  2. 使用在方法上

@ConfigurationProperties中的几个属性作用

public @interface ConfigurationProperties {

	@AliasFor("prefix")
	String value() default "";

	@AliasFor("value")
	String prefix() default "";

	boolean ignoreInvalidFields() default false;

	boolean ignoreUnknownFields() default true;
}

valueprefix功能相同,比较容易理解就是将指定的前缀属性绑定到这个Bean上的属性。
ignoreInvalidFields:默认false表示绑定到此对象时应忽略无效字段。指示绑定到此对象时应忽略无效字段。一般是字段类型错误(或无法强制转换为正确类型),例如:实体类中定义的可能是一个Boolean类型,但是配置项的值却是日期。则这个时候会报错.
ignoreUnknownFields: 默认true,表示绑定到此对象时应忽略实体类中不存在的字段。例如配置项中可能有一个同样前缀的配置,但是实体类中没有对应的属性.

使用在类上

prefix示例

首先完成一个基础demo,在springboot的配置文件中(默认application.properties)编写对应的配置项值。

datasource.config.read-only=false
datasource.config.url=localhost
datasource.config.username=bruce
datasource.config.pwd=123456

编写实体类

@Component
@ConfigurationProperties(prefix = "datasource.config")
public class DataSourceProperties {

    private String url;
    private String pwd;
    private String username;
    private Boolean readOnly;
    // Setter/Getter
}

使用绑定后的属性值

@SpringBootTest
class Demo1ApplicationTests {

    @Autowired
    private DataSourceProperties dataSourceProperties;

    @Test
    void contextLoads() {
        System.out.println(dataSourceProperties);
    }
}

打印结果如下,正确绑定了属性值.
在这里插入图片描述
ignoreInvalidFields示例:
将application.properties中的配置修改为如下的值

datasource.config.read-only=aa
......其他属性不变

默认由于 “aa” 无法转为Boolean类型,所以报错
在这里插入图片描述
@ConfigurationProperties(prefix = "datasource.config")添加**ignoreInvalidFields=true**
@ConfigurationProperties(prefix = "datasource.config", ignoreInvalidFields=true)
此时执行程序可以正常执行

ignoreUnknownFields示例:
在application.properties中多添加一个相同前缀的配置,但实际上DataSourceProperties中并不存在同名的属性

datasource.config.poolSize=12

默认不会报错

但是在@ConfigurationProperties(prefix = "datasource.config")添加**ignoreUnknownFields=false**
@ConfigurationProperties(prefix = "datasource.config", ignoreUnknownFields=false)
此时执行程序则会报错
在这里插入图片描述
一般情况下只需要指定@ConfigurationProperties注解的prefix属性即可,其它注解属性保持默认值还是比较合理的。

使用在方法上

org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
		matchIfMissing = true)
static class Hikari {

	@Bean
	@ConfigurationProperties(prefix = "spring.datasource.hikari")
	HikariDataSource dataSource(DataSourceProperties properties) {
		HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
		if (StringUtils.hasText(properties.getName())) {
			dataSource.setPoolName(properties.getName());
		}
		return dataSource;
	}

}

当方法返回对象之后,springboot会将指定前缀的属性值再绑定到对象属性上。也就是配置项优先级高于代码赋值。

原理分析:
spring在解析类时,会将所有带@Bean方法包装成ConfigurationClassBeanDefinition注册到spring中,ConfigurationClassBeanDefinition包含了SimpleMethodMetadata信息,用于反射调用方法,SimpleMethodMetadata里则存有方法上的注解信息.

注册MethodBeanDefinition的源码:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
在这里插入图片描述
方法返回值属性绑定的流程:
当调用方法创建对象之后,会经过ConfigurationPropertiesBindingPostProcessor#postProcessBeforeInitialization方法,调用ConfigurationPropertiesBean#get(ApplicationContext applicationContext, Object bean, String beanName)方法,从spring中获取原先注册的ConfigurationClassBeanDefinition,从中拿到Method,判断方法上是否有@ConfigurationProperties注解。如果没有,返回null,不需要绑定属性值。如果有则创建ConfigurationPropertiesBean,调用绑定属性值的方法。最后返回Bean对象。

相关源码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值