Yaml(yml)
最近比較流行的配置檔案,相對properties,配置檔案結構更清晰簡潔.前段時間項目需要引入的配置,于是想用
yml
檔案來增加新的屬性配置,新增屬性放在
application.yml
中是沒問題的,但是放其他檔案中,然後通過
@PropertySource
引入時,卻出現了問題,所有
.yml
中的參數配置全部讀取無效,properties檔案是正常的,後來在stackoverflow上看到
@PropertySource
中存在
factory
參數,通過配置
factory
參數可以達到我們想要的效果。
@PropertySource factory
屬性的
factory
預設配置是
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
, 我們再看下
PropertySourceFactory
的源碼就可知道了,
/**
* Strategy interface for creating resource-based {@link PropertySource} wrappers.
*
* @author Juergen Hoeller
* @since 4.3
* @see DefaultPropertySourceFactory
*/
public interface PropertySourceFactory {
/**
* Create a {@link PropertySource} that wraps the given resource.
* @param name the name of the property source
* @param resource the resource (potentially encoded) to wrap
* @return the new {@link PropertySource} (never {@code null})
* @throws IOException if resource resolution failed
*/
PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException;
}
預設實作是
DefaultPropertySourceFactory
,
/**
* The default implementation for {@link PropertySourceFactory},
* wrapping every resource in a {@link ResourcePropertySource}.
*
* @author Juergen Hoeller
* @since 4.3
* @see PropertySourceFactory
* @see ResourcePropertySource
*/
public class DefaultPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
}
}
我們所有做的隻需繼承DefaultPropertySourceFactory,然後對createPropertySource作下微調,就可以支援yaml了.
public class MixPropertySourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
String sourceName = name != null ? name : resource.getResource().getFilename();
if (!resource.getResource().exists()) {
return new PropertiesPropertySource(sourceName, new Properties());
} else if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
Properties propertiesFromYaml = loadYml(resource);
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
} else {
return super.createPropertySource(name, resource);
}
}
private Properties loadYml(EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
}
這裡做了個簡單的檔案字尾判斷,如果是以.yml或.yaml結尾,則通過YamlPropertiesFactoryBean加載,其他情況則采用預設方式加載.如果大家需要支援json或xml等其他格式,也可在這裡自動加入政策處理.
最後在SpringApplication上加入配置
@PropertySource(value = {
"a.properties",
"b.yml"
}, factory = MixPropertySourceFactory.class)
就可以了