简体   繁体   English

春季缓存仅在某些时候有效

[英]Spring caching works only sometimes

I have a Spring controller and want to cache the response. 我有一个Spring控制器,想缓存响应。 When I move the @Cacheable annotation from the getBooks to the doGetBooks method, the caching will stop. 当我将@Cacheable注释从getBooks移到doGetBooks方法时,缓存将停止。 Once I move it back to the getBooks method caching works again. 一旦将其移回getBooks方法,缓存将再次起作用。 Why is that and how can I fix it? 为什么会这样,我该如何解决?

This will cache the public method response 这将缓存公共方法响应

@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{
    ...

This will never cache the private method response 这将永远不会缓存私有方法响应

@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{
    ...

Problem: You are calling doGetBooks() within the same class, and Spring cache requires an AOP proxy to the called method. 问题:您在同一类中调用doGetBooks(),并且Spring缓存需要AOP代理到被调用的方法。

This is a good discussion describing why Spring AOP can not intercept methods called by other class methods: AOP calling methods within methods 这是一个很好的讨论,描述了Spring AOP为什么不能拦截其他类方法调用的方法 :方法中的AOP调​​用方法

There are at least three workarounds: 至少有三种解决方法:

  1. Refactor the code: Move doGetBooks() into another @Component, and invoke the method using that (injected) bean (refactoredBean.doGetBooks()) 重构代码:将doGetBooks()移至另一个@Component,并使用该(注入的)bean(refactoredBean.doGetBooks())调用该方法。
  2. Create a self-reference to the service invoking the call (By @Autowired private MyService myservice and invoke myservice.doGetBooks(). 创建对调用调用的服务的自引用(通过@Autowired private MyService myservice并调用myservice.doGetBooks()。
  3. Using the ApplicationContext to cast the service bean, and invoking the method on that bean. 使用ApplicationContext强制转换服务bean,并在该bean上调用方法。

Once you invoke a method that Spring Cache can intercept (via AOP), then the @Cacheable() annotation should trigger. 一旦调用了Spring Cache可以拦截(通过AOP)的方法,那么@Cacheable()批注就应该触发。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM