GeXiangDong

精通Java、SQL、Spring的拼写,擅长Linux、Windows的开关机

0%

@Value vs. @ConfigurationProperties

@Value和@ConfigurationProperties两个注解都可以从配置文件获取值并设置到属性中,用法上有区别。

@Value适用一些比较简单的情形,用得比较普遍;而@ConfigurationProperties则可适用一些@Value无法处理更复杂的情形。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
myapp:
simple:
name: ABC
count: 15
countries: CN,US,UK
complex:
list:
- id: k1
value: hello
- id: k2
value: nihao
- id: k3
value: konichiha
nested:
name: John
address:
province: jiangsu
city: nanjing

例如上面的配置myapp.simple下的属性都可以用@value获取到,甚至myapp.simple.countries也可以被设置到String[]类型的属性上,但是下面的myapp.complex.list设置的配置,@Value就无法把它转成一个List<Map<String, Object>>类型的属性了,而@ConfigurationProperties可以。甚至myapp.complex.nested还可以被@ConfigurationProperties付值到带有两个属性(province, city)的子类中(参照下面的@ NestedConfigurationProperty注解)

@Value

可处理的类型

只可处理String、数值等简单类型,和简单的数组类型,不能处理map、List等复杂类型

位置

直接写在需要从配置文件读取值的成员变量上即可。
例如:

1
2
3
4
5
@Service
public class XxxxService{
@Value("${xxx.yyy}")
private String xxxYyy;
}

参数

只有一个字符型参数value,用于标记配置文件中的key

参数名称 类型 默认值 说明
value String 从配置文件中哪一项读取值,支持Spring EL

@ConfigurationProperties

可处理的类型

除了基本类型外,List、Map、 数组, 自定义POJO …

用法

@ConfigurationProperties注解需要写到类上,为该类所有有setter方法的属性从配置文件中读取并付值。@ConfigurationProperties 只能在类上使用,不能用在属性上。

如果类里面的某个属性是另外一个POJO,则在该属性上增加注解 @NestedConfigurationProperty , 这样就可嵌套解析。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@ConfigurationProperties
public class xxxYyy{
private String name;
@NestedConfigurationProperty Address address;

public void setName(String name){
this.name = name;
}

public void setAddress(Address address){
this.address = address;
}
}

public class Address{
private String province;
private String city;

//---略过setter方法
}

参数

参数名称 类型 默认值 说明
ignoreInvalidFields boolean false java中被绑定的属性类型与配置文件中设置的值类型不同时是否忽略
ignoreUnknownFields boolean true Flag to indicate that when binding to this object invalid fields should be ignored
prefix String The name prefix of the properties that are valid to bind to this object.
value String 同prefix,简写,支持Spring EL

前置条件

1、需要增加依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

2、需要先开始使用配置属性的功能(不开启不出错,但不会读取配置并设置到类上)

1
@EnableConfigurationProperties

@EnableConfigurationProperties需要写在Spring Boot的启动类或配置类上。

从其他配置文件中读取

如果信息配置在了自定义的配置文件中(不是applicaiton.yml),则可以使用@PropertySource注解来告诉spring从哪个文件读取配置信息,例如:

1
@PropertySource("classpath:configprops.properties")

@PropertySource 注解默认只能解析 properties 文件,如果是yml文件,需要自定义一个解析器

如果需要从其他yml文件读取配置,可以利用 @PropertySource 的 factory 属性,先写一个解析yml 文件的类,这很简单,因为spring中已经包含了解析yml格式的解析器,我们只需要包装一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

import java.io.IOException;
import java.util.Properties;

public class YamlPropertySourceFactory implements PropertySourceFactory {
private static final Logger logger = LoggerFactory.getLogger(YamlPropertySourceFactory.class);

@Override
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource)
throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(encodedResource.getResource());
Properties properties = factory.getObject();
logger.trace(
"read from {}, exists:{}",
encodedResource.getResource().getFile().getAbsoluteFile(),
encodedResource.getResource().exists());
return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
}
}

之后在使用 @PropertySource 注解时增加 factory 属性

1
@PropertySource(factory = YamlPropertySourceFactory.class, value = "classpath:yamlfile.yml")