Spring Cache - @CacheEvict,@CachePut 在从同一类的另一个方法调用时不起作用
Posted
技术标签:
【中文标题】Spring Cache - @CacheEvict,@CachePut 在从同一类的另一个方法调用时不起作用【英文标题】:Spring Cache - @CacheEvict, @CachePut not working while calling from the another method from the same class 【发布时间】:2021-01-28 21:03:34 【问题描述】:从同一类的另一个方法调用缓存方法时,Spring 缓存不起作用。
这是一个清楚地解释我的问题的例子。
缓存服务类:
class testServiceImpl
@CachePut(key = "#result.id", condition = "#result != null")
public List<String> create(String input)
......
@CacheEvict(key="#id")
public void deleteById(Long id)
.....
public void multiDelete(String input)
if(condition...)
deleteById(2); //Cache is not Evicted here i.e. the records are still present in getAll call but not in Database.
else
create(input); //New Data is persisted in DB but the same has not been updated in Cache.
@Transactional
@Cacheable
public Map<Long, String> getAll()
...
我也尝试过使用以下解决方案,但未能成功。
//Create a new object of the same class and use the same. In this case, the data is not persisted in DB i.e. it is not deleting the data from DB.
testServiceImpl testService;
...
public void multiDelete(String input)
if(condition...)
testService.deleteById(2);
else
testService.create(input);
有人可以帮我解决这个问题吗?
【问题讨论】:
你看过这个吗? ***.com/questions/16899604/… @cdalxndr 的答案是正确的。比使用 AspectJ 更好的解决方案是直接调用缓存。您可以通过感染CacheManager
并致电getCache(name)
来做到这一点
【参考方案1】:
当您从服务调用方法时,实际上是通过代理调用它。自动装配的 bean 被包装在一个代理中,该代理拦截调用并仅为该方法处理缓存注释。
当你在内部进行调用时,它是直接在服务对象上进行的,并且没有代理包装器,缓存注解不会被处理。 See Understanding AOP Proxies
一种可行的替代方法是使用AspectJ,它将处理缓存注释的spring方面直接编织到代码中,而不使用任何Spring代理,因此您可以调用内部方法并且缓存注释将按预期处理。
【讨论】:
你能举一个 AspectJ 的例子吗?我如何在这里使用 AspectJ 来解决这个问题? @AmitAgarwal 我个人建议不要使用 AspectJ,因为您可能会进入一个难以调试问题的世界。如果你喜欢冒险,基本上你需要使用spring-boot-starter-aop
,添加spring-aspects
依赖,设置@EnableCaching(mode = AdviceMode.ASPECTJ)
,并添加VM选项-javaagent:<path to aspectjweaver.jar>
进行加载时间编织。以上是关于Spring Cache - @CacheEvict,@CachePut 在从同一类的另一个方法调用时不起作用的主要内容,如果未能解决你的问题,请参考以下文章