Spring上下文属性占位符ehcache配置

7
我有一个Spring上下文XML文件,其中包含以下内容:
<context:property-placeholder location="classpath:cacheConfig.properties"/>

<bean id="cacheManager"
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="cacheManagerName" value="cacheName"/>
    <property name="shared" value="false"/>
    <property name="configLocation" value="classpath:cacheConfig.xml"/>
</bean>

目标是允许客户像这样编辑属性文件

cache.maxMemoryElements="2000"

然后在实际的cacheConfig.xml文件中添加以下内容

<cache name="someCacheName"
   maxElementsInMemory="${cache.maxMemoryElements}" ... />

为了避免客户更改我们不想要的项目,我们需要隐藏它们。当然,以上细节只是部分详细信息,目前在日志文件中看到:

Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Error configuring from input stream. Initial cause was null:149: Could not set attribute "maxElementsInMemory".

Thanks in advance...

4个回答

12

你的示例使用EhCacheManagerFactoryBean将对外部cacheConfig.xml文件中定义的缓存,暴露为CacheManager的引用。正如@ChssPly76所指出的,Spring的属性解析器只能在Spring自己的bean定义文件中工作。

但是,你不必在外部文件中定义单独的缓存,可以在Spring bean定义文件中使用EhCacheFactoryBean来定义它们:

  

FactoryBean创建了一个名为EHCache Cache实例...如果指定的命名缓存未在缓存配置描述符中配置,则此FactoryBean将构造具有提供的名称和指定缓存属性的Cache实例,并将其添加到CacheManager以供以后检索。

换句话说,如果你使用EhCacheFactoryBean来引用一个在cacheConfig.xml中尚未定义的命名缓存,那么Spring将在运行时创建并配置一个新的缓存实例,并向CacheManager注册它。这包括指定像maxElementsInMemory这样的内容,因为这将在Spring bean定义文件中指定,所以你可以完全支持属性解析器:

<context:property-placeholder location="classpath:cacheConfig.properties"/>

<bean id="myCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    <property name="cacheManager" ref="cacheManager"/>
    <property name="maxElementsInMemory" value="${cache.maxMemoryElements}"/>
</bean>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="shared" value="false"/>
    <property name="configLocation" value="classpath:cacheConfig.xml"/>
</bean>

谢谢!这让我足够克服难关,以至于我可以达到我想要的目标。 - Dennis S
3
如果您想配置的不是缓存,该怎么办?例如,cacheManagerPeerListenerFactory的属性? - Emil Sit

3
这不是 PropertyPlaceholderConfigurer 的工作方式。它可以用于替换上下文内的值,但不能替换任意外部文件中的值。而cacheConfig.xml是一个外部文件 - 它只是由 Spring 传递给 EH Cache。

2

如果您需要修改磁盘存储路径,而无法像ehcache javadoc所述设置diskstore参数,则可以创建自己的EhCacheManagerFactoryBean实现,允许您注入diskstore路径;您基本上需要拦截CacheManager的创建,并使用您的diskstore属性修改传递的配置,例如:

private String diskStorePath;

...getter/setter


public void afterPropertiesSet() throws IOException, CacheException {
    if (this.shared) {
        // Shared CacheManager singleton at the VM level.
        if (this.configLocation != null) {
            this.cacheManager = CacheManager.create(this.createConfig());
        }
        else {
            this.cacheManager = CacheManager.create();
        }
    }
    else {
        // Independent CacheManager instance (the default).
        if (this.configLocation != null) {
            this.cacheManager = new CacheManager(this.createConfig());
        }
        else {
            this.cacheManager = new CacheManager();
        }
    }
    if (this.cacheManagerName != null) {
        this.cacheManager.setName(this.cacheManagerName);
    }
}

private Configuration createConfig() throws CacheException, IOException {
    Configuration config = ConfigurationFactory.parseConfiguration(this.configLocation.getInputStream());

    DiskStoreConfiguration diskStoreConfiguration = config.getDiskStoreConfiguration();
    if (diskStoreConfiguration == null) {
        DiskStoreConfiguration diskStoreConfigurationParameter = new DiskStoreConfiguration();
        diskStoreConfigurationParameter.setPath(getDiskStorePath());
        config.addDiskStore(diskStoreConfigurationParameter);
    } else {
        diskStoreConfiguration.setPath(getDiskStorePath());
    }

    return config;
}

Spring的配置应该是这样的:

<bean id="cacheManager" class="com.yourcompany.package.MyEhCacheManagerFactoryBean" depends-on="placeholderConfig">
    <property name="diskStorePath" value="${diskstore.path}"/>
    <property name="configLocation" value="classpath:ehcache.xml" />
</bean>

仅为补充此有益帖子:如果您需要访问 JNDI 属性,则可以通过以下方式设置:<property name="diskStorePath" value="$jndi{property/ehcache/diskstore}"/>。 - Martin

2
如果您正在使用Maven或Ant,两者都提供了在资源文件中过滤令牌的功能。
对于Maven,您可以执行以下操作:
<cache name="someCacheName"
  maxElementsInMemory="${cache.maxMemoryElements}" ... />

在过滤器文件中或者在POM本身中,需要有以下内容:
 cache.maxMemoryElements = 200

Maven中的资源过滤:权威指南

在Ant中,可以使用FilterSets<copy>任务来完成此操作。


1
+1,但需要记住的重要事情是,无论是Ant还是Maven,在属性替换时都发生在构建时间,而不是Spring的属性占位符,在运行时发生。 - ChssPly76

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接