我正在使用Spring缓存注释,但是发现其中发生了一些奇怪的事情。
说我要在同一服务类中调用带有@CachePut批注的方法。不会被缓存。
如果我将该方法移至其他服务实现文件并调用该方法,缓存将起作用。
我需要知道我在做什么错。
答案 0 :(得分:1)
假设您使用@CachePut
public class FooBean implements Foo{
@CachePut
public String doSomething(){
}
}
在后台运行Spring将创建一个AOP代理,该代理将包装您的类,以便可以在调用实际的@CachePut
方法之前或之后应用一些缓存魔术代码。您可以认为AOP代理看起来像:
public class FooBeanProxy implements Foo{
private FooBean fooBean;
public String doSomething(){
//Maybe there are some caching magic codes here....
fooBean.doSomething()
//Maybe there are other caching magic codes here........
}
}
如果我将该方法移至其他服务实现文件,并且 调用该方法可以正常工作。
假设您执行以下操作以调用@CachePut
方法:
@Component
public class App {
//FooBeanProxy actually injected HERE
@Autowired
private Foo foo;
public void startDoing(){
foo.doSomething();
}
}
Spring为您注入的是FooBeanProxy
,而不是您的FooBean。因此,当您调用该@CachePut
方法时,缓存魔术代码将在您调用FooBeanProxy
说我正在具有@CachePut的同一服务类中调用方法 其中的注释。不会被缓存。
这意味着它是自我调用。您要调用的是 this 参考,它是您的FooBean
实例,但现在不再是FooBeanProxy
。因此,这些缓存魔术将永远不会执行,因此结果将不会被缓存。
实际上,我在docs中已经提到了我上面所说的内容。如果您仍然希望@CachePut
在自调用的情况下生效,则可以使用docs中提到的可怕而丑陋的AopContext.currentProxy()
解决方案,也可以使用AspectJ
。