天天看點

SpringBoot配置檔案@PropertySource 同時支援properties檔案與yaml(yml)

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)
           

就可以了

繼續閱讀