远程PropertySource

时间:2014-08-12 18:29:07

标签: spring

有没有人幸运构建一个使用远程源(例如数据库)从中检索属性值的PropertySource。想法是构造一个PropertySource(需要一些连接信息,如主机/端口)并将其插入PropertySourcePlaceholderConfigurer。

问题似乎是鸡和蛋的问题。如何将连接信息下载到PropertySource?我可以首先使用配置实例化PropertySourcePlaceholderConfigurer,以使用远程主机和端口属性加载属性文件,然后稍后实例化PropertySource并将其注入配置器。但是,我似乎无法确定第一个实例化(并快速注入配置器)的bean是我的属性源。我需要这个,因为当然,我所有的其他bean都依赖于远程属性。

2 个答案:

答案 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;
  }
}