【问题标题】:Remote PropertySource远程财产来源
【发布时间】:2014-08-12 18:29:06
【问题描述】:

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

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

【问题讨论】:

    标签: spring


    【解决方案1】:

    Commons Configuration 支持通过org.apache.commons.configuration.ConfigurationBuilder 将来自各种源(包括JDBC 数据源)的属性加载到org.apache.commons.configuration.Configuration 对象中。

    使用org.apache.commons.configuration.ConfiguratorConverter,您可以将Configuration 对象转换为可以传递给PropertySourcesPlaceholderConfigurer 的java.util.Properties 对象。

    至于如何配置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 Configuration所需的文件:

    【讨论】:

    • 这对我来说是一个解决方案......当你发布这个时,我实际上只是在输入一个类似的解决方案。我将在下面发布我的解决方案。谢谢@Ricardo Veguilla
    【解决方案2】:

    与上面 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;
      }
    }
    

    【讨论】:

    • 您介意分享您对实际 PropertySource 的实现吗?
    • PropertySource 只是一个spring框架类:org.springframework.core.env.PropertySource
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多