Spring 缓存只是有时有效

Spring caching works only sometimes

我有一个 Spring 控制器并想缓存响应。当我将 @Cacheable 注释从 getBooks 移动到 doGetBooks 方法时,缓存将停止。一旦我将它移回 getBooks 方法,缓存就会再次工作。为什么会这样,我该如何解决?

这将缓存 public 方法响应

@GetMapping
@Cacheable(value = "cache", key = "{ #root.methodName }")
public Books getBooks(@RequestHeader(value = "user-agent", required = false) String userAgent) throws Exception {
     if(valid) {
          return this.doGetBooks();
     }
     throw new Exception();
}


public Books doGetBooks() throws Exception{
    ...

这将永远不会缓存私有方法响应

@GetMapping
public Books getBooks(@RequestHeader(value = "user-agent", required = false) String userAgent) throws Exception {
     if(valid) {
          return this.getBooks();
     }
     throw new Exception();
}


@Cacheable(value = "cache", key = "{ #root.methodName }")
public Books doGetBooks() throws Exception{
    ...

问题:您在同一个 class 中调用 doGetBooks(),并且 Spring 缓存需要被调用方法的 AOP 代理。

这是一个很好的讨论,描述了为什么 Spring AOP 不能拦截其他 class 方法调用的方法:AOP calling methods within methods

至少有三种解决方法:

  1. 重构代码:将 doGetBooks() 移动到另一个 @Component 中,并使用该(注入的)bean 调用该方法 (refactoredBean.doGetBooks())
  2. 创建对调用服务的自引用(通过@Autowired private MyService myservice 并调用 myservice.doGetBooks()。
  3. 使用 ApplicationContext 转换服务 bean,并调用该 bean 上的方法。

一旦调用了 Spring 缓存可以拦截(通过 AOP)的方法,@Cacheable() 注释就会触发。