【问题标题】:Spring AOP does not work with self-invocation such as @CachePutSpring AOP 不适用于 @CachePut 等自调用
【发布时间】:2019-01-19 18:27:42
【问题描述】:

我正在研究 Spring 缓存注解,但我发现其中发生了一些奇怪的事情。

假设我在同一个服务类中调用一个方法,其中包含 @CachePut 注释。那没有被缓存。

如果我将该方法移动到其他服务实现文件并调用该方法缓存正在工作。

我需要知道我做错了什么。

【问题讨论】:

  • AOP 是支持缓存功能的幕后英雄。 Spring aop 一般使用 cglib 或 java 代理,会为目标 bean 做一个代理。所以从外部调用将抛出代理,目标bean中的内部调用将直接方式。

标签: spring spring-boot aop


【解决方案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

【讨论】:

  • 鉴于您描述的确切场景,如果方法 doSomething() 是私有方法,您如何使其工作?
猜你喜欢
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2019-10-30
  • 2010-10-02
相关资源
最近更新 更多