有没有人幸运构建一个使用远程源(例如数据库)从中检索属性值的PropertySource。想法是构造一个PropertySource(需要一些连接信息,如主机/端口)并将其插入PropertySourcePlaceholderConfigurer。
问题似乎是鸡和蛋的问题。如何将连接信息下载到PropertySource?我可以首先使用配置实例化PropertySourcePlaceholderConfigurer,以使用远程主机和端口属性加载属性文件,然后稍后实例化PropertySource并将其注入配置器。但是,我似乎无法确定第一个实例化(并快速注入配置器)的bean是我的属性源。我需要这个,因为当然,我所有的其他bean都依赖于远程属性。
答案 0 :(得分:2)
Commons Configuration 支持通过org.apache.commons.configuration.Configuration
将各种来源(包括JDBC数据源)的属性加载到org.apache.commons.configuration.ConfigurationBuilder
对象中。
使用org.apache.commons.configuration.ConfiguratorConverter
,您可以将Configuration对象转换为java.util.Properties
对象,该对象可以传递给PropertySourcesPlaceholderConfigurer。
关于如何配置ConfigurationBuilder的鸡和蛋问题,我建议使用org.springframework.core.env.Environment
来查询系统属性,命令行属性或JNDI属性。
在这个例子中:
@Configuration
public class RemotePropertyConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer(Environment environment)
throws Exception {
final PropertySourcesPlaceholderConfigurer props = new PropertySourcesPlaceholderConfigurer();
final ConfigurationBuilder configurationBuilder = new DefaultConfigurationBuilder(environment.getProperty("configuration.definition.file"));
props.setProperties(ConfigurationConverter.getProperties(configurationBuilder.getConfiguration()));
return props;
}
您需要指定环境属性configuration.definition.file
,该属性指向配置Commons配置所需的文件:
答案 1 :(得分:0)
与Recardo上面的回答类似,我使用的是Spring的PropertiesLoaderUtils而不是Apache的,但它的含义相同。它并不完全理想..硬编码依赖注入,但嘿,它的工作原理!
/**
* This method must remain static as it's part of spring's initialization effort.
* @return
**/
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
String dbHost = null;
Integer dbPort = null;
// check system / environment properties first
Environment environment = new StandardEnvironment();
if (environment.containsProperty(DB_HOST_KEY)) {
dbHost = environment.getProperty(DB_HOST_KEY);
}
if (environment.containsProperty(DB_PORT_KEY)) {
dbPort = Integer.valueOf(environment.getProperty(DB_PORT_KEY));
}
if (dbHost == null || dbPort == null) {
// ok one or (probably) both properties null, let's go find the database.properties file
Properties dbProperties;
try {
dbProperties = PropertiesLoaderUtils.loadProperties(new EncodedResource(new ClassPathResource("database.properties"), "UTF-8"));
}
catch (IOException e) {
throw new RuntimeException("Could not load database.properties. Please confirm the file is in the classpath");
}
if (dbHost == null) {
dbHost = dbProperties.getProperty(DB_HOST_KEY);
}
if (dbPort == null) {
dbPort = Integer.valueOf(dbProperties.getProperty(DB_PORT_KEY));
}
}
PropertySourceService propertySourceService = new DBPropertySourceService(dbHost, dbPort);
PropertySource<PropertySourceService> propertySource = new DBPropertySource(propertySourceService);
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addFirst(propertySource);
configurer.setPropertySources(propertySources);
return configurer;
}
每个请求,这是远程属性源的来源。它依赖于一个'服务'类,可以做..好吧..任何东西..通过套接字远程访问属性,与数据库通信,等等。
/**
* Property source for use with spring's PropertySourcesPlaceholderConfigurer where the source is a service
* that connects to remote server for property values.
**/
public class RemotePropertySource extends PropertySource<PropertySourceService> {
private final Environment environment;
/**
* Constructor...
* @param name
* @param source
**/
public RemotePropertySource(PropertySourceService source) {
super("RemotePropertySource", source);
environment = new StandardEnvironment();
}
/* (non-Javadoc)
* @see org.springframework.core.env.PropertySource#getProperty(java.lang.String)
*/
@Override
public Object getProperty(String name) {
// check system / environment properties first
String value;
if (environment.containsProperty(name)) {
value = environment.getProperty(name);
}
else {
value = source.getProperty(name);
}
return value;
}
}