由Typesafe配置支持的Spring环境

我想在我的项目中使用typesafe配置(HOCON配置文件),这有助于简化和组织应用程序配置。 目前我正在使用普通的Java属性文件(application.properties),这在大项目中很难处理。

我的项目是Spring MVC(不是Spring启动项目)。 有没有办法支持我的Spring环境(我将注入到我的服务中)以支持typesafe配置。 这不应该像@Value注释,@ @Autowired Environment等那样制止我现有的环境使用。

如何以最小的努力和我的代码更改来完成此操作。

这是我目前的解决方案:寻找还有其他更好的方法

 @Configuration public class PropertyLoader{ private static Logger logger = LoggerFactory.getLogger(PropertyLoader.class); @Bean @Autowired public static PropertySourcesPlaceholderConfigurer properties(Environment env) { PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer(); Config conf = ConfigFactory.load(); conf.resolve(); TypesafePropertySource propertySource = new TypesafePropertySource("hoconSource", conf); ConfigurableEnvironment environment = (StandardEnvironment)env; MutablePropertySources propertySources = environment.getPropertySources(); propertySources.addLast(propertySource); pspc.setPropertySources(propertySources); return pspc; } } class TypesafePropertySource extends PropertySource{ public TypesafePropertySource(String name, Config source) { super(name, source); } @Override public Object getProperty(String name) { return this.getSource().getAnyRef(name); } } 

我认为我提出了比手动将PropertySource添加到属性源更加惯用的方法。 创建一个PropertySourceFactory并使用@PropertySource引用它

首先,我们有一个类似于你拥有的TypesafeConfigPropertySource

 public class TypesafeConfigPropertySource extends PropertySource { public TypesafeConfigPropertySource(String name, Config source) { super(name, source); } @Override public Object getProperty(String path) { if (source.hasPath(path)) { return source.getAnyRef(path); } return null; } } 

接下来,我们创建一个返回该属性源的PropertySource 工厂

 public class TypesafePropertySourceFactory implements PropertySourceFactory { @Override public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { Config config = ConfigFactory.load(resource.getResource().getFilename()).resolve(); String safeName = name == null ? "typeSafe" : name; return new TypesafeConfigPropertySource(safeName, config); } } 

最后,在我们的配置文件中,我们可以像任何其他PropertySource一样引用属性源,而不必自己添加PropertySource:

 @Configuration @PropertySource(factory=TypesafePropertySourceFactory.class, value="someconfig.conf") public class PropertyLoader { // Nothing needed here } 

你创建一个PropertySource类,如下所示,它与你的类似,区别在于你必须返回值或null并且不让lib抛出一个丢失的exception

 public class TypesafeConfigPropertySource extends PropertySource { private static final Logger LOG = getLogger(TypesafeConfigPropertySource.class); public TypesafeConfigPropertySource(String name, Config source) { super(name, source); } @Override public Object getProperty(String name) { try { return source.getAnyRef(name); } catch (ConfigException.Missing missing) { LOG.trace("Property requested [{}] is not set", name); return null; } } } 

第二步是按如下方式定义bean

  @Bean public TypesafeConfigPropertySource provideTypesafeConfigPropertySource( ConfigurableEnvironment env) { Config conf = ConfigFactory.load().resolve(); TypesafeConfigPropertySource source = new TypesafeConfigPropertySource("typeSafe", conf); MutablePropertySources sources = env.getPropertySources(); sources.addFirst(source); // Choose if you want it first or last return source; } 

如果您想要将属性自动assembly到其他bean,您需要使用注释@DependsOn到propertysource bean,以确保它首次加载

希望能帮助到你

Laplie Anderson回答了一些小改进:

  • 如果找不到资源,则抛出exception
  • 忽略包含[:字符的路径

TypesafePropertySourceFactory.java

 import java.io.IOException; import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; import com.typesafe.config.ConfigParseOptions; import com.typesafe.config.ConfigResolveOptions; public class TypesafePropertySourceFactory implements PropertySourceFactory { @Override public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { Config config = ConfigFactory .load(resource.getResource().getFilename(), ConfigParseOptions.defaults().setAllowMissing(false), ConfigResolveOptions.noSystem()).resolve(); String safeName = name == null ? "typeSafe" : name; return new TypesafeConfigPropertySource(safeName, config); } } 

TypesafeConfigPropertySource .java

 import org.springframework.core.env.PropertySource; import com.typesafe.config.Config; public class TypesafeConfigPropertySource extends PropertySource { public TypesafeConfigPropertySource(String name, Config source) { super(name, source); } @Override public Object getProperty(String path) { if (path.contains("[")) return null; if (path.contains(":")) return null; if (source.hasPath(path)) { return source.getAnyRef(path); } return null; } } 
Interesting Posts