【问题标题】:Can I use PropertyPlaceholderConfigurer to perform replacement of properties on String at runtime?我可以使用 PropertyPlaceholderConfigurer 在运行时替换 String 上的属性吗?
【发布时间】:2012-04-19 17:28:09
【问题描述】:

在我们正在使用的 Spring 配置的一个领域中:

applicationContext.xml

<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" lazy-init="true">
    <property name="configLocation" value="classpath:ehcache.xml"/>
</bean>

但是,ehcache.xml 不是标准的 spring bean 配置文件,而是包含 ${ehcache.providerURL},我们希望根据我们在其他地方使用 PropertyPlaceHolderConfigurer 配置的内容来替换它:

ehcache.xml

<cacheManagerPeerProviderFactory
   ...
   providerURL=${ehcache.providerURL}
   ...
</cacheManagerPeerProviderFactory>

我可以使用 Maven/profile/filter 组合,但这会创建一个特定于其构建环境的构建。我真正想做的是在运行时预处理 ehcache.xml,根据 PropertyPlaceHolderConfigurer 读取的属性执行替换,然后将结果传递给 EhCacheManagerBean。

此时,我正在考虑以某种方式复制@Value 注释背后的功能,因为它可以替换“bla bla bla ${property} bla bla bla”,除非我需要在从磁盘读取文件后执行此操作。

关于如何解决这个问题的任何想法?

谢谢。 -AP_

【问题讨论】:

    标签: spring ehcache


    【解决方案1】:

    要直接操作字符串,您可以使用 org.springframework.util.PropertyPlaceholderHelper

    String template = "Key : ${key} value: ${value} "
    PropertyPlaceholderHelper h = new PropertyPlaceholderHelper("${","}");
    Properties p = new Properties(); 
    p.setProperty("key","mykey");
    p.setProperty("value","myvalue");
    String out = h.replacePlaceholders(template,p);
    

    它将模板中的值替换为相应的属性值。

    【讨论】:

      【解决方案2】:

      经过一番搜索,这是我想出的精髓。我将它打包成一个工厂,它接受资源并在将所有行替换为 ${propertyPlaceHolder} 与持有者的实际值之后进行转换。

          final ConfigurableListableBeanFactory
              factory =
                  ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
      
          String line = null;
          while ((line = reader.readLine()) != null) {
              try {
                  final String
                      result = factory.resolveEmbeddedValue(line);
                  writer.println(result);
              }
              catch (final Exception e) {
                  log.error("Exception received while processing: " + line, e);
                  throw e;
              }
          }
      

      此解决方案的好处是它使用与 Spring 用于解析 @Value("${fooBar}") 注释相同的工具。这意味着您可以使用 SpEL 以及 Spring 通常在 @Value 注释中接受的任何其他内容。它还与 PropertyPlaceholderConfigurer 集成。

      希望这对某人有所帮助。

      -AP_

      【讨论】:

        【解决方案3】:

        PropertyPlaceholderConfigurer 用于替换 Spring 配置文件中的属性。它不会替换外部文件中的属性。 PropertyPlaceholderConfigurer 无法解决您的问题。

        您可以在创建 CacheManager 之前覆盖 org.springframework.cache.ehcache.EhCacheManagerFactoryBean.afterPropertiesSet() 方法并使用 xml 做任何您想做的事情。您知道它有多干净 :)

        【讨论】:

        • Spring 中有一些代码采用 @Value("bla ${param} bla) 并正确进行替换。我正在考虑在运行时以某种方式使用此代码来传递我的内容文件作为字符串,并取回一个替换参数的字符串。
        • 经过一番挖掘,我发现了这个: ((ConfigurableApplicationContext) applicationContext).getBeanFactory().resolveEmbeddedValue("${someValue}");我可以读取任何旧文件,然后使用此方法解析所有占位符。 Spring 中是否有任何东西可以让我从 bean 配置中执行此操作而无需编写更多代码?
        • 我认为 Adi 的回答是一个相当不错的 hack。将 XML 读入字符串,对需要的部分进行字符串替换,将字符串设置为配置位置(InputStreamResource/StringBufferInputStream),然后调用 super.
        • Adi,如果我没有成功地使用更通用的方法来过滤 ${propertyPlaceHolders} 的任何文件,我肯定会使用您的解决方案。事实证明,我发现了另一种情况,我们正在配置休眠二级缓存,所以我需要一个更通用的解决方案。
        猜你喜欢
        • 1970-01-01
        • 2011-10-04
        • 2017-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-26
        • 2022-01-07
        相关资源
        最近更新 更多