【问题标题】:Spring cache not working with EHCache+JCacheSpring 缓存不适用于 EHCache+JCache
【发布时间】:2023-08-21 14:19:02
【问题描述】:

我正在尝试将 jcache 的 ehcache 实现集成到 spring 中。所以我有一个这样定义的外观:

@Component(value = "sampleFacade")
 @CacheDefaults(cacheName = "default")
 public class SampleFacadeImpl implements SampleFacade
 {

   @Override
   @CacheResult(cacheName = "site")
    public SitePojo getSiteForUid(final String uid)
    {
        System.out.println("getting the site for uid: " + uid);

        final SitePojo pojo = new SitePojo();
        pojo.setUid(uid);
        pojo.setUrl(uid);

        return pojo;
    }
}

还有一个基于 java 的配置,如下所示:

@Configuration
@EnableCaching(mode = AdviceMode.PROXY)
@ComponentScan(basePackages = { "com.test" })
public class TestConfig implements CachingConfigurer
{
   @Resource
   public ApplicationContext context;

   @Override
   @Bean(name = { "defaultKeyGenerator", "keyGenerator" })
   public KeyGenerator keyGenerator() {
       return new SimpleKeyGenerator();
   }

   @Override
   @Bean(name = { "defaultCacheManager", "cacheManager" })
   public CacheManager cacheManager() {
       final JCacheCacheManager cacheManager = new JCacheCacheManager();
       cacheManager.setCacheManager((javax.cache.CacheManager) context.getBean("cacheManagerFactoryBean"));

       return cacheManager;
   }

   @Bean(name = { "defaultCacheManagerFactoryBean", "cacheManagerFactoryBean" })
   protected JCacheManagerFactoryBean defaultCacheManagerFactoryBean() {
       return new JCacheManagerFactoryBean();
   }
}

还有一个调用门面 10 次的测试:

@Test
public void testGetSiteForUid() {
    for (int i = 0; i < 10; i++) {
        assertNotNull(sampleFacade.getSiteForUid("uid"));
    }
}

但结果是通过方法10次:

getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid
getting the site for uid: uid

您可以在此处找到一个示例项目来重现它: https://github.com/paranoiabla/spring-cache-test

【问题讨论】:

    标签: java spring ehcache spring-cache jcache


    【解决方案1】:

    JCache 支持是 Spring 4.1 的一个新特性。您使用的 4.0.4 尚不支持此功能。

    Spring Framework 4.1 尚未发布。您可以通过将以下内容添加到您的项目来尝试快照

    <repositories>
      <repository>
        <id>spring-snapshot</id>
        <name>Springframework Snapshot Repository</name>
        <url>http://repo.spring.io/snapshot</url>
        <snapshots>
          <enabled>true</enabled>
        </snapshots>
      </repository>
    </repositories>
    

    然后将spring.version 翻转为4.1.0.BUILD-SNAPSHOT

    我已经分叉了您的项目并更新了it here,以便它可以正常工作。 Checking what I've changed 将帮助您了解缺少的内容。

    注意:您的 JSR-107 缓存管理器是错误的。你应该创建一个javax.cache.CacheManager,一旦你有了它,你应该把它包装到Spring的CacheManager。请记住,您也可以在此处声明 any CacheManager,它会起作用(SimpleCacheManagerGuavaCacheManager 等)。

    【讨论】:

    • 嗨,我尝试了你的建议,它显示了这个错误:java.lang.IllegalArgumentException: Cannot find cache named 'site' for CacheResultOperation[details[method=public com.test.cache.SitePojo com. test.cache.impl.SampleFacadeImpl.getCurrentSite(), cacheAnnotation=@javax.cache.annotation.CacheResult(cacheKeyGenerator=interface javax.cache.annotation.CacheKeyGenerator, cacheResolverFactory=interface javax.cache.annotation.CacheResolverFactory, cachedExceptions=[], skipGet=false, exceptionCacheName=, cacheName=site, nonCachedExceptions=[]), cacheName='site']]
    • 嗨,我试过你的建议,它显示这个错误:嗨,我试过你的建议,它显示这个错误:我在你的临时应用程序中看到你使用 SimpleCacheManager 像这样: SimpleCacheManager manager = new SimpleCacheManager( ); manager.setCaches(asList(new ConcurrentMapCache("default"), new ConcurrentMapCache("another")) );退货经理;但不幸的是 JCacheCacheManager 没有 setCaches 方法。如何为我的 JCacheCacheManager 指定缓存?
    • 我认为您应该重新访问ehcache-jcache 以及如何配置它。这可能是创建另一个线程的好主意,因为这与 Spring 无关(这是一个纯粹的 JSR-107 ehcache 问题)。与此同时,您可以直接使用普通的 ehcache 或查看我的 fork(我编辑了我的原始答案)