使用注解将 EhCache XML 转换为 Java 类并在 JMX 中注册

问题描述

在我们的项目中,我们有两个模块:api 和 api-component,每个模块都有一个 cache.xml 文件,该文件引用另一个 ehcache.xml 文件,如下所示:

cache.xml(在两个模块中)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="ehcache" />
    </bean>

    <bean id="ehcache"
        class="org.springframework.cache.ehcache.EhCacheManagerfactorybean"
        p:config-location="classpath:ehcache.xml" />

    <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerfactorybean">
        <property name="locateExistingServerIfPossible" value="true" />
    </bean>

    <bean class="net.sf.ehcache.management.ManagementService"
        init-method="init">
        <constructor-arg ref="ehcache" />
        <constructor-arg ref="mbeanServer" />
        <constructor-arg value="true" />
        <constructor-arg value="true" />
        <constructor-arg value="true" />
        <constructor-arg value="true" />
    </bean>

</beans>

ehcache.xml(在两个模块中)

<ehcache name="ApiCacheManager">
    <diskStore path="java.io.tmpdir"/>

    <cache name="myCache" -- Different name in each file
           maxElementsInMemory="1000"
           eternal="false"
           timetoIdleSeconds="500"
           timetoLiveSeconds="500"
           overflowTodisk="false"
           statistics="true"
    />
​
    <defaultCache
            maxElementsInMemory="1000"
            eternal="true"
            overflowTodisk="false"
    />
</ehcache>

为了使用注释将这些 XML 文件转换为 Java 类,我想出了这些配置,同样在两个模块中:ApiCacheConfiguration.java 和 ApiComponentCacheConfiguration.java

import net.sf.ehcache.Cache;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.diskStoreConfiguration;
import net.sf.ehcache.management.ManagementService;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.interceptor.*;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jmx.support.MBeanServerfactorybean;

import java.util.Collections;

@Configuration
@EnableCaching
public class ApiCacheConfiguration extends CachingConfigurerSupport {

    @Primary
    @Bean
    public CacheManager cacheManager() {
        CompositeCacheManager compositeCacheManager = new CompositeCacheManager();
        compositeCacheManager.setCacheManagers(Collections.singleton(ehCacheManager()));
        return compositeCacheManager;
    }

    @Bean
    public EhCacheCacheManager ehCacheManager() {
        EhCacheCacheManager cacheManager = new EhCacheCacheManager(ehCacheCacheManager());

        ManagementService.registerMBeans(
                cacheManager.getCacheManager(),mBeanServer().getobject(),true,true);

        return cacheManager;
    }

    @Bean
    public MBeanServerfactorybean mBeanServer() {
        MBeanServerfactorybean mBeanServerfactorybean = new MBeanServerfactorybean();
        mBeanServerfactorybean.setLocateExistingServerIfPossible(true);
        return mBeanServerfactorybean;
    }

    @Bean
    @Override
    public CacheResolver cacheResolver() {
        return new SimpleCacheResolver(cacheManager());
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
        return new SimpleCacheErrorHandler();
    }

    private net.sf.ehcache.CacheManager ehCacheCacheManager() {
        net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(ehCacheConfiguration());
        cacheManager.setName("ApiCacheManager"); // If name is not set I'm not getting 'InstanceAlreadyExistsException'
        cacheManager.addCache(myCache());
        return cacheManager;
    }

    private Cache myCache() {
        CacheConfiguration configuration = new CacheConfiguration("myCache",100) // Different name in each file
                .eternal(false)
                .timetoIdleSeconds(600)
                .timetoLiveSeconds(3600)
                .overflowTodisk(false)
                .statistics(true);
        return new Cache(configuration);
    }

    private net.sf.ehcache.config.Configuration ehCacheConfiguration() {
        diskStoreConfiguration diskStoreConfiguration = new diskStoreConfiguration();
        diskStoreConfiguration.setPath("java.io.tmpdir");

        CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();
        defaultCacheConfiguration.maxElementsInMemory(1000);
        defaultCacheConfiguration.eternal(true);
        defaultCacheConfiguration.overflowTodisk(false);

        net.sf.ehcache.config.Configuration configuration = new net.sf.ehcache.config.Configuration();
        configuration.setDefaultCacheConfiguration(defaultCacheConfiguration);
        configuration.adddiskStore(diskStoreConfiguration);
        return configuration;
    }

}

一切都和之前的 ehCache.xml 写的差不多,但是,我不知道是怎么回事,正在创建 ApiCacheManager 和 ApiComponentCacheManager 的多个 bean,抛出这些错误

Caused by: javax.management.InstanceAlreadyExistsException: net.sf.ehcache:type=CacheManager,name=ApiCacheManager

Caused by: javax.management.InstanceAlreadyExistsException: net.sf.ehcache:type=CacheManager,name=ApiComponentCacheManager

如果未设置 CacheManager 名称,则不会出现此错误,但多个 bean 已注册到 JMX:

enter image description here

如何使用我设置的名称仅将我的两个 CacheManager 放入 JMX? CacheManager 的创建有什么问题吗?也许不是创建单例?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...