一、@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 依赖,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
否则相应类上会有一行红色的异常信息,具体如下:
Spring Boot Configuration Annotation Processor not found in classpath
并且在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")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
}
注:注释@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)
|