一文教会你如何让spring @PropertySource支持读取yaml文件
- 背景介绍
- 实现思路
- 具体实现
-
- 使用演示
- 进阶思考
-
- 使用演示
背景介绍
通过之前的文章(点击查看)我们已经知道@PropertySource默认支持读取properties文件和xml文件,如果我们想让@PropertySource支持yaml文件的话,需要编写自定义factory。今天我们就来编写一个自定义的factory来实现这个功能。
实现思路
public class DefaultPropertySourceFactory implements PropertySourceFactory {
public DefaultPropertySourceFactory() {
}
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
return name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource);
}
}
@PropertySource默认使用的factory是DefaultPropertySourceFactory。从源码中,我们可以看到,自定义factory需要实现PropertySourceFactory接口的createPropertySource方法。
另外spring自带了YamlPropertiesFactoryBean类,这个类提供了将yaml配置文件解析为Properties的能力,借助这个类,我们就可以编写支持yaml文件的factory。
具体实现
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
// 如果没有传入名称则取文件名
String sourceName = name != null ? name : resource.getResource().getFilename();
// 新建FactoryBean解析配置文件
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
// 返回解析后的结果
return new PropertiesPropertySource(sourceName, factory.getObject());
}
}
使用演示
test.yaml文件
actor:
name: li.zhou
age: 18
@SpringBootApplication
@PropertySource(value = {"file:D:\\test.yml"}, factory = YamlPropertySourceFactory.class)
public class SpringPropertyApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(SpringPropertyApplication.class, args);
Environment environment = applicationContext.getEnvironment();
// 输出:li.zhou
System.out.println(environment.getProperty("actor.name"));
}
}
进阶思考
虽然yaml文件是支持了,但是和properties与xml是割裂的,无法混合使用。于是我们在原来的基础上进一步编写factory支持3种格式的混合使用。
public class SmartPropertySourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
String sourceName = name != null ? name : resource.getResource().getFilename();
if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
YamlPropertySourceFactory yamlPropertySourceFactory = new YamlPropertySourceFactory();
return yamlPropertySourceFactory.createPropertySource(name, resource);
} else {
return super.createPropertySource(name, resource);
}
}
}
使用演示
test1.properties
properties.name=li.zhou
@SpringBootApplication
@PropertySource(value = {"file:D:\\test.yml", "file:D:\\test1.properties"},
factory = SmartPropertySourceFactory.class)
public class SpringPropertyApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(SpringPropertyApplication.class, args);
Environment environment = applicationContext.getEnvironment();
// 打印均为li.zhou
System.out.println(environment.getProperty("actor.name"));
System.out.println(environment.getProperty("properties.name"));
}
}