背景
在SpringBoot项目中,有时需要引入除application.yml
之外的配置文件(例如在开发公共组件时)。使用@PropertySource
注解可以实现这一需求,但有一些细节点需要注意,在此记录。
代码实现
假设有一份名为extra.yml
的配置文件:
# extra.yml
extra:
name: 张三
order: 3
对应的配置bean为:
@Data
@ConfigurationProperties("extra")
public class ExtraProperties {
private String name;
private Integer order;
}
在配置类上添加相关注解,将extra.yml
配置文件添加到Spring环境中:
@Configuration
@EnableConfigurationProperties(ExtraProperties.class)
@PropertySource(
// 配置文件路径
value = "classpath:/extra.yml",
// 当配置文件不存在时,是忽略还是报错
ignoreResourceNotFound = true,
// 配置文件编码
encoding = "UTF-8",
// 配置文件加载工厂
factory = YamlPropertySourceFactory.class)
public class ExtraConfig {
}
由于@PropertySource
默认支持的是.properties
格式的配置文件,而我们一般使用的是YAML格式的,因此这里自定义了配置文件加载工厂,支持YAML,并解决ignoreResourceNotFound
不生效的问题:
/**
* YAML配置文件加载工厂
*/
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
try {
return new YamlPropertySourceLoader()
.load(resource.getResource().getFilename(), resource.getResource())
.get(0);
} catch (IllegalStateException e) {
// 如果YAML配置文件不存在,希望能忽略该文件,而不是引发异常导致Spring容器启动失败
// 需要往外抛FileNotFoundException,Spring捕捉到后会忽略该异常(当 ignoreResourceNotFound = true 时)
if (e.getCause() instanceof FileNotFoundException) {
throw (FileNotFoundException) e.getCause();
} else {
throw e;
}
}
}
}
这样,ExtraProperties
配置bean里的属性值, 就与extra.yml
里的配置值绑定在一起了。
补充说明
标准配置文件application.yml
的生效优先级高于额外引入的配置文件。如果application.yml
中指定了相同的配置项,则它会覆盖extra.yml
中对应的配置项:
# application.yml,会覆盖extra.yml中的相同配置项
extra:
name: 李四
order: 4
当然,如果使用了环境配置文件application-{profile}.yml
,则它的生效优先级又会高于application.yml
。
另外,@PropertySource
支持引入多个配置文件。例如,在引入extra.yml
的同时,引入对应的环境配置文件extra-{profile}.yml
:
@Configuration
@EnableConfigurationProperties(ExtraProperties.class)
@PropertySource(
value = {"classpath:/extra.yml", "classpath:/extra-${spring.profiles.active}.yml"},
ignoreResourceNotFound = true,
encoding = "UTF-8",
// 配置文件加载工厂
factory = YamlPropertySourceFactory.class)
public class ExtraConfig {
}
这里,Spring会将占位符${spring.profiles.active}
解析为对应的值。例如,在application.yml
中指定spring.profiles.active=dev
,那么配置文件extra-dev.yml
会被引入(如有),它的生效优先级高于extra.yml
,但低于application.yml
。
# extra-dev.yml,会覆盖extra.yml中的相同配置项
extra:
name: 王五
order: 5
总结
@PropertySource
用于引入额外的配置文件。- 通过自定义配置文件加载工厂,可支持YAML文件解析,并支持
ignoreResourceNotFound
。 - 配置文件生效的优先级顺序为:
application-{profile}.yml
>application.yml
>extra-{profile}.yml
>extra.yml
。