《SpringBoot系列三》:自定义配置时@Value和@ConfigurationProperties孰优孰劣?

网友投稿 390 2022-09-17

《SpringBoot系列三》:自定义配置时@Value和@ConfigurationProperties孰优孰劣?

一、@Value

通过@Value我们可以直接将属性值注入到IOC容器的相应bean 中,业务上我们注入单个属性时最常使用的也是这种方式。

不过,有时使用​​@Value("${property}")​​注解来注入配置属性有时会很麻烦,尤其是当要使用多个属性 或 数据本质上是分层的 时。

所以,Spring Boot 提供了一种使用属性的替代方法,可以让​​强类型 bean​​ 管理和验证应用程序的配置。

使用方式:

需要使用到属性的JavaBean中:

@Value("${test.test}")private String test;

yaml文件:

test: test: test-resources/

二、@ConfigurationProperties

​​@ConfigurationProperties​​​加载配置是通过BeanPostProcessor实现,其对应的Bean的后置处理器为​​ConfigurationPropertiesBindingPostProcessor​​​。也就是说在bean被实例化后,会调用后置处理器,递归的查找属性,通过反射机制注入值,因此属性需要提供setter和getter方法。 此外,针对此种属性注入的方式,SpringBoot支持​​​Relaxed Binding​​,即只需保证配置文件的属性和setter方法名相同即可。

在SpringBoot官方文档中有几个注意点:

属性必须要有getter、setter方法;如果属性的类型是集合,要确保集合是不可变的;如果使用Lombok自动生成getter/setter方法,一定不要生成对应的任何构造函数,因为Spring IOC容器会自动使用它来实例化对象。使用JavaBean属性绑定的方式只针对​​标准 Java Bean 属性​​,不支持对静态属性的绑定。

当我们使用​​@ConfigurationProperties​​​注解进行属性注入时,记得在pom.xml文件中添加​​spring-boot-configuration-processor​​依赖,

org.springframework.boot spring-boot-configuration-processor true

否则相应类上会有一行红色的异常信息,具体如下:

Spring Boot Configuration Annotation Processor

并且在pom中加上​​spring-boot-configuration-processor​​​依赖之后,我们使用​​@ConfigurationProperties​​注解注释的配置类中的字段,在yaml文件中会自动带出提示 / 补全。

1、@EnableConfigurationProperties

Spring考虑到带有注释​​@ConfigurationProperties​​​的类可能不适合扫描(比如:我正在开发自己的自动配置或希望有条件地启用它们),所以Spring并不会自动扫描带有注释​​@ConfigurationProperties​​的类。

在这些情况下,推荐使用​​@EnableConfigurationProperties​​​注解指定要处理的类型列表(即:将​​@ConfigurationProperties​​​注释的类加到Spring IOC容器中)。一般通过将​​@EnableConfigurationProperties​​​加在​​@Configuration​​类上完成。

使用方式1:@EnableConfigurationProperties + @Configuration + @ConfigurationProperties

如下例所示:

@Configuration(proxyBeanMethods = false)@EnableConfigurationProperties(SomeProperties.class)public class MyConfiguration {}

@ConfigurationProperties(prefix = "some.properties")public class SomeProperties { private String test;}

这种方式在Spring源码中被广泛使用:

比如:Spring MVC的配置类(WebMvcProperties)

其在​​WebMvcAutoConfiguration​​​类的静态内部类​​WebMvcAutoConfigurationAdapter​​上被通过@Configuration + @EnableConfigurationProperties的方式被注入到Spring IOC容器中。

使用方式2:@Configuration + @ConfigurationProperties

直接将​​@Configuration​​​注解 和 ​​@ConfigurationProperties​​​注解加在JavaBean上,让Spring IOC可以自动扫描到 ​​@ConfigurationProperties​​注解标注的类。

@Configuration(proxyBeanMethods = false)@ConfigurationProperties(prefix = "some.properties")public class SomeProperties { private String test;}

2、宽松绑定(Relaxed Binding)

Spring Boot 中使用一些宽松的规则将​​环境属性(可以理解为配置文件application.yml中的属性)​​​绑定到bean中,也就是说:yaml文件中的属性名称和 JavaBean属性名称​​@ConfigurationProperties​​之间不需要完全匹配。包括:

破折号分隔的环境属性(context-path绑定到contextPath)大写环境属性(PORT绑定到port)

例如,考虑以下@ConfigurationProperties类:

@ConfigurationProperties(prefix = "my.main-project.person")public class MyPersonProperties { private String firstName; public String getFirstName() { return this.firstName; } public void setFirstName(String firstName) { this.firstName = firstName; }}

使用上述代码时,可以使用以下属性名称:

Property

Note

my.main-project.person.first-name

Kebab case,通常使用在 ​​.properties​​​ 和 ​​.yml​​ 文件中

my.main-project.person.firstName

标准驼峰方式

my.main-project.person.first_name

下划线表示法,在​​.properties​​​ 和 ​​.yml​​文件中使用的另一种格式

MY_MAINPROJECT_PERSON_FIRSTNAME

大写格式,在使用系统环境变量时推荐使用

注意:@ConfigurationProperties注解中​​prefix​​的值必须是 kebab 大小写(小写并用 分隔-,例如my.main-project.person)

每种属性源的宽松绑定规则

3、JSR-303对@ConfigurationProperties验证

每当使用 Spring 的注解​​@Validated​​进行注解时,Spring Boot 都会尝试验证类。我们可以直接在配置类上使用 JSR-303约束注释。

@ConfigurationProperties("my.service")@Validatedpublic class MyProperties { @NotNull private InetAddress remoteAddress; // getters/setters...}

注:注释@Bean创建配置属性的方法来也可以触发验证@Validated

4、第三方配置

@ConfigurationProperties除了用于注释类之外,还可以在公共@Bean方法上使用它。当想要将属性绑定到我们无法控制的第三方组件时,这样做会特别有用。

@Configuration(proxyBeanMethods = false)public class ThirdPartyConfiguration { @Bean @ConfigurationProperties(prefix = "another") public AnotherComponent anotherComponent() { return new AnotherComponent(); }}

三、@Value和@ConfigurationProperties的区别?

@ConfigurationProperties注解支持属性文件和javabean的映射;而@Value支持spel表达式。@ConfigurationProperties注解支持全量的属性 宽松绑定方式;而@Value只推荐使用标准的​​kebab-case​​​方式(仅使用小写字母和​​-​​​),例如:​​@Value("{demo.item-price}")​​​可以提取​​demo.item-price​​​和​​demo.itemPrice​​。对于多个属性映射,并且属性常常被复用时,推荐使用@ConfigurationProperties;只读取单个属性使用@Value更简单方便。

四、SpringBoot配置加载优先级

移步至:​​SprintBoot:配置文件加载优先级(含服务注册中心nacos)​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:hi老家,这个春节我还能回吗?
下一篇:原来MyBatis插件/拦截器(Plugin/Interceptyor)的实现原理这么简单
相关文章

 发表评论

暂时没有评论,来抢沙发吧~