问题
I have a Spring controller and want to cache the response. When I move the @Cacheable
annotation from the getBooks
to the doGetBooks
method, the caching will stop. Once I move it back to the getBooks
method caching works again. 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{
...
回答1:
Problem: You are calling doGetBooks() within the same class, and Spring cache requires an AOP proxy to the called method.
This is a good discussion describing why Spring AOP can not intercept methods called by other class methods: AOP calling methods within methods
There are at least three workarounds:
- Refactor the code: Move doGetBooks() into another @Component, and invoke the method using that (injected) bean (refactoredBean.doGetBooks())
- Create a self-reference to the service invoking the call (By @Autowired private MyService myservice and invoke myservice.doGetBooks().
- Using the ApplicationContext to cast the service bean, and invoking the method on that bean.
Once you invoke a method that Spring Cache can intercept (via AOP), then the @Cacheable() annotation should trigger.
来源:https://stackoverflow.com/questions/48408121/spring-caching-works-only-sometimes