1. 程式人生 > >spring aop類方法之間呼叫切面不能匹配

spring aop類方法之間呼叫切面不能匹配

參考:https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#aop-understanding-aop-proxies

public class SimplePojo implements Pojo {

    public void foo() {
        // this next method invocation is a direct call on the 'this' reference
        this.bar();
    }

    public void bar() {
        // some logic...
    }
}

你會發現foo方法呼叫的bar方法並沒有織入對應的增強。

原因分析:

AOP的本質是:通過建立新的代理物件,在代理物件裡面新增對應的增強程式碼實現。完成代理物件的呼叫,即完成了增強的過程。

public class SimplePojoProxy implements Pojo {
   Pojo pojo;
  
    public void foo() {
        before();
		pojo.foo();
        after();
    }

    public void bar() {
        before();
		pojo.bar();
        after();
    }
}

如上,SimplePojoProxy代理物件呼叫foo方法,切入了對應的增強,但是在foo方法呼叫bar方法的時候,其實是針對pojo也就是目標物件發生呼叫的(目標物件方法中並沒有對應的增強),而非SimplePojoProxy代理的bar方法,所以導致增強失效。

在這裡插入圖片描述

解決方案1:

注意:使用這種方式必須設定aop-config標籤的expose-proxy屬性為true,具體原理請參考AOPUtils分析

public class SimplePojo implements Pojo {

    public void foo() {
        ((Pojo) AopContext.currentProxy()).bar();
    }

    public void bar() {
        // some logic...
    }
}

解決方案2

public class Main {

    public static void main(String[] args) {

        ProxyFactory factory = new ProxyFactory(new SimplePojo());
        factory.adddInterface(Pojo.class);
        factory.addAdvice(new RetryAdvice());
        factory.setExposeProxy(true);

        Pojo pojo = (Pojo) factory.getProxy();

        // this is a method call on the proxy!
        pojo.foo();
    }
}