Grails 4中@CachePut无法向命名缓存添加键致缓存失效
问题分析与解决方案
核心原因1:内部方法调用导致Spring AOP代理失效
你的代码中testCache()方法直接在内部调用了testCachePut(),而Spring的缓存注解(包括@CachePut、@Cacheable)是基于动态代理实现的。当方法在类内部直接调用时,不会经过代理对象,因此注解逻辑完全不会触发——这就是@CachePut只创建缓存但不写入键值的根本原因。
解决办法
拆分方法到不同Service:将
testCachePut()移到另一个独立的Service类中,通过依赖注入的方式调用,确保走代理触发缓存逻辑:// 新建独立的PutCacheService class PutCacheService { @CachePut(value='testCache', key='k1') String testCachePut(m){ println "called put" return "return Value for testCachePut, param m: $m" } } // 原CacheService中注入调用 class CacheService { PutCacheService putCacheService @Cacheable(value='testCache', key='k1') def testCache(m){ println "called testCache with m: $m" putCacheService.testCachePut(m) } }使用自身代理对象调用:如果不想拆分类,可以通过获取当前类的代理对象来调用方法:
- 在
application.groovy中开启代理暴露:grails.spring.proxy.config = [exposeProxy: true] - 修改
CacheService中的调用逻辑:import org.springframework.aop.framework.AopContext @Cacheable(value='testCache', key='k1') def testCache(m){ println "called testCache with m: $m" ((CacheService)AopContext.currentProxy()).testCachePut(m) }
- 在
核心原因2:缓存管理器冲突
你同时配置了Hibernate的Ehcache和Grails Cache插件,两者共用缓存管理器可能导致配置冲突,干扰缓存写入逻辑。
解决办法
明确配置Grails Cache插件的独立缓存管理器,与Hibernate缓存区分开。在application.groovy中添加:
grails { cache { enabled = true config = { cacheManager { name = 'grailsCacheManager' } } } }
如果不需要Hibernate二级缓存与Grails业务缓存共用,可进一步为两者配置独立的Ehcache配置文件。
日志排查优化
当前logback配置仅开启了Hibernate缓存日志,需添加Grails Cache相关日志定位问题:
logger("org.grails.plugins.cache", DEBUG, ['STDOUT']) logger("net.sf.ehcache", DEBUG, ['STDOUT'])
开启后可查看缓存的创建、写入、读取全过程日志,便于排查细节问题。
内容的提问来源于stack exchange,提问作者Dirk27
相关产品推荐
相关产品推荐

