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
至少有三种解决方法:
- 重构代码:将 doGetBooks() 移动到另一个 @Component 中,并使用该(注入的)bean 调用该方法 (refactoredBean.doGetBooks())
- 创建对调用服务的自引用(通过@Autowired private MyService myservice 并调用 myservice.doGetBooks()。
- 使用 ApplicationContext 转换服务 bean,并调用该 bean 上的方法。
一旦调用了 Spring 缓存可以拦截(通过 AOP)的方法,@Cacheable() 注释就会触发。
我有一个 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
至少有三种解决方法:
- 重构代码:将 doGetBooks() 移动到另一个 @Component 中,并使用该(注入的)bean 调用该方法 (refactoredBean.doGetBooks())
- 创建对调用服务的自引用(通过@Autowired private MyService myservice 并调用 myservice.doGetBooks()。
- 使用 ApplicationContext 转换服务 bean,并调用该 bean 上的方法。
一旦调用了 Spring 缓存可以拦截(通过 AOP)的方法,@Cacheable() 注释就会触发。