一文教會你如何讓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"));
}
}