【问题标题】:How to invoke Spring's current property placeholder on resource in java code?java - 如何在java代码中的资源上调用Spring的当前属性占位符?
【发布时间】:2013-01-24 04:45:50
【问题描述】:

Spring 占位符机制非常干净和健壮,不幸的是它只适用于 Spring 文件。

我正在使用 EhCahe,我想在 ehcache.xml 文件上使用占位符机制。我有自己的 EhCache 工厂 bean,我可以将此库配置作为 InputStream 提供。所以我需要做的就是实现我的目标:

  • 从类路径读取 xml 文件内容
  • 访问属性占位符当前 spring.xml 文件(我的 bean 已配置)
  • 在读取资源上调用占位符
  • 将资源作为 InputStream 还给库

所以我的问题是,如何做到这一点,就像 Spring 允许的那样紧凑?我想避免自己创建占位符,所以代码会尽可能少地“魔法”,所以我想使用 xml 文件中的属性配置。

【问题讨论】:

    标签: java spring ehcache placeholder


    【解决方案1】:

    EhCache 支持 ehcache.xml 文件中的系统属性占位符替换,因此一种选择是将 Spring 占位符值复制到系统属性中,以便在 ehcache.xml 文件中引用它们:

    在spring上下文xml中...

    <!-- Copy Spring placeholder value to System props -->
    <bean id="systemProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" value="#{@systemProperties}" />
        <property name="targetMethod" value="putAll" />
        <property name="arguments">
            <util:properties>
                <prop key="cache.ttl">${cache.ttl}</prop>
            </util:properties>
        </property>
    </bean>
    

    然后在您的 ehcache.xml 文件中,您现在可以使用上面填充的 ${cache.ttl} 占位符:

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
        <cache name="myCache" timeToLiveSeconds="${cache.ttl}" maxElementsInMemory="1000" overflowToDisk="false" />
    </ehcache>
    

    【讨论】:

    【解决方案2】:

    Ehcache 有一个以编程方式定义新缓存的 api。为什么你不能做一个与春天一起启动并自动填充的豆子?这样你就不必创建一个自动的 EhCache.xml,但是你可以在一个 spring 上下文文件中定义你想要的所有缓存。

    【讨论】:

    • 你的意思是把ehcache.xml改写成spring.xml bean格式?它仍然是一种选择,但是对于习惯使用 ehcache.xml 格式的人来说,这是一个令人震惊的选择,迫使他们学习“新”格式。
    【解决方案3】:

    不必使用系统属性。但是,您必须在构建期间解析占位符。

    像这样把你的属性放到对象中:

    <bean id="cacheProperties" class="java.util.Properties">
        <constructor-arg>
            <props>
                <prop key="prop1">#{prop1}</prop>
                <prop key="prop2">#{prop2}</prop>
            </props>
        </constructor-arg>
    </bean>
    

    并将它们设置为您的自定义 PlaceHolderHelper:

        <bean id="cachePlaceholderHelper"
          class="com.PlaceholderHelper" depends-on="cacheProperties">
        <property name="configFileResource" value="classpath:cacheConfig.xml"/>
        <property name="properties" ref="cacheProperties"/>
    </bean>
    

    PlaceholderHelper 可能看起来像这样:

    private Resource configFileResource;
    private Properties properties;
    private Resource resolvedConfigResource;
    
    @PostConstruct
    public void replace() throws IOException {
        PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}");
    
        if (this.properties != null && this.configFileResource != null) {
            File file = this.configFileResource.getFile();
            String content = FileUtils.readFileToString(file);
            String result = helper.replacePlaceholders(content, this.properties);
            File resolvedCacheConfigFile = new File("resolvedCacheConfig");
            FileUtils.write(resolvedCacheConfigFile, result);
    
            resolvedConfigResource = new FileSystemResource(resolvedCacheConfigFile);
            logger.info(String.format("Placeholders in file %s were replaced.", file.getName()));
        }
    }
    

    将 p:configLocation 更改为已解析的资源:

    p:configLocation="#{cachePlaceholderHelper.resolvedConfigResource}
    

    现在您可以在 XML 的任何地方使用 ${prop1} 表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      • 2018-04-28
      • 2017-02-20
      • 1970-01-01
      • 2017-12-17
      • 2011-01-13
      • 1970-01-01
      相关资源
      最近更新 更多