Spring缓存 - 在从同一类的另一个方法调用时@CacheEvict、@CachePut无效

4

当从同一类的另一个方法调用缓存方法时,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); 
            }

有人可以帮助我解决这个问题吗?


2
你看过这个吗?https://dev59.com/wmQn5IYBdhLWcg3wW2D3?rq=1 - Shawrup
@cdalxndr的答案是正确的。比使用AspectJ更好的解决方案是直接调用缓存。您可以通过注入“CacheManager”并调用“getCache(name)”来实现。 - cruftex
1个回答

5

当您从您的服务调用方法时,实际上是通过代理来调用它。自动装配的bean被包装在一个代理中,该代理拦截调用并仅处理该方法的缓存注释。

当您在内部进行调用时,它直接在服务对象上进行,并且没有代理封装,缓存注释不会被处理。 请参见了解AOP代理

一种可行的替代方法是使用 AspectJ ,它会将处理缓存注释的 Spring 方面编织到代码中,而不使用任何 Spring 代理,因此您可以调用内部方法并且缓存注释将如预期一样得到处理。


你能用AspectJ举个例子吗?我该如何在这里使用AspectJ来解决这个问题呢? - Amit Agarwal
@AmitAgarwal 我个人建议不要使用AspectJ,因为你可能会遇到难以调试的问题。如果你想冒险的话,基本上你需要使用spring-boot-starter-aop,添加spring-aspects依赖项,设置@EnableCaching(mode = AdviceMode.ASPECTJ),并添加VM选项-javaagent:<path to aspectjweaver.jar>进行加载时编织。 - cdalxndr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接