Spring Boot自定义驱逐方法无法清除缓存问题咨询
问题原因及解决方案
核心问题不是evictByFooId缺少注解,而是Spring缓存注解基于AOP代理实现,类内部直接调用带缓存注解的方法不会触发代理逻辑。
你写的evictByFooId是直接调用同一个类里的evictByTestId,这时候走的是对象本身的方法调用,跳过了Spring生成的代理对象,所以evictByTestId上的@CacheEvict注解根本没生效,自然清不掉缓存。
几种可行的解决办法:
1. 注入自身代理对象调用
在类里注入当前类的代理实例,通过代理对象调用evictByTestId:
@Component @CacheConfig(cacheNames = ["test"]) class TestCache { @Autowired private lateinit var selfProxy: TestCache @Cacheable(cacheNames = ["test"], key = "#testId") fun find(testId: String): String { ... } @CachePut(cacheNames = ["test"], key = "#testId") fun put(testId: String, set: String): String { ... } @CacheEvict(cacheNames = ["test"], key = "#testId") fun evictByTestId(testId: String) { } fun evictByFooId(fooId: String): Boolean { /* some processing to convert fooId to testId */ val testId = fooId selfProxy.evictByTestId(testId) return true } }
2. 直接给evictByFooId加@CacheEvict注解
如果fooId转testId的逻辑可以用SpEL表达式实现,直接在evictByFooId上标注注解,把转换逻辑写到key里:
@Component @CacheConfig(cacheNames = ["test"]) class TestCache { @Cacheable(cacheNames = ["test"], key = "#testId") fun find(testId: String): String { ... } @CachePut(cacheNames = ["test"], key = "#testId") fun put(testId: String, set: String): String { ... } @CacheEvict(cacheNames = ["test"], key = "#testId") fun evictByTestId(testId: String) { } @CacheEvict(cacheNames = ["test"], key = "#fooId") // 替换成实际转换逻辑,比如T(com.yourpackage.Utils).convertFooToTest(#fooId) fun evictByFooId(fooId: String): Boolean { return true } }
3. 拆分逻辑到独立组件
把缓存操作的逻辑抽成单独的组件,比如TestCacheManager,然后在TestCache里注入这个组件调用,这样调用就会走代理:
@Component class TestCacheManager { @CacheEvict(cacheNames = ["test"], key = "#testId") fun evictByTestId(testId: String) { } } @Component @CacheConfig(cacheNames = ["test"]) class TestCache { @Autowired private lateinit var cacheManager: TestCacheManager @Cacheable(cacheNames = ["test"], key = "#testId") fun find(testId: String): String { ... } @CachePut(cacheNames = ["test"], key = "#testId") fun put(testId: String, set: String): String { ... } fun evictByFooId(fooId: String): Boolean { val testId = fooId cacheManager.evictByTestId(testId) return true } }
内容的提问来源于stack exchange,提问作者waquner
相关产品推荐
相关产品推荐

