解決SpringAop內部調用時不經過代理類的問題

SpringAop

AOP代理織入時期

  • 編譯時織入 – aspectj框架
  • 類加載時織入 – aspectj框架
  • 運行時織入 – spring-aop

動態代理方式

  • JDK – 被代理對象必須需要實現接口
  • CGLIB – 采用繼承被代理對象方式實現代理功能

解決SpringAop內部調用時不經過代理類(而是通過this)

方案一

通過編譯時織入或者類加載時織入代碼

方案二

通過當前代理類調用目標方法

getOne()方法中直接調用getAll()時是通過this對象,這時候getAll()方法上的@AopLog就不會被AOP掃描到

@Service
@Slf4j
public class ServiceImpl implements IService {
    @Override
    @AopLog("value=getOne")
    public void getOne() {
        log.info("getOne running");
        // 直接調用getAll()方法 = this.getAll()
        getAll();
    }
    @Override
    @AopLog("value=getAll")
    public void getAll() {
        log.info("getAll running");
    }
}

修改getOne()方法,通過AopContext.currentProxy()方法獲取當前代理類,通過代理類來調用getAll()方法,這時候就是通過代理類調用的

@Service
@Slf4j
public class ServiceImpl implements IService {
    @Override
    @AopLog("value=getOne")
    public void getOne() {
        log.info("getOne running");
        // 獲取當前代理類,通過代理類來調用getAll()方法
        ((IService) AopContext.currentProxy()).getAll();
    }
    @Override
    @AopLog("value=getAll")
    public void getAll() {
        log.info("getAll running");
    }
    @AopLog("value=getById")
    private void getById() {
        log.info("getById running");
    }
}

this使得SpringAop失效之謎

問題描述

類Demo被AOP掃描到,其中有A和B兩個方法,A方法中調用瞭B方法,執行A方法時,B方法的代理沒有生效

問題剖析

我們知道AOP底層使用JDK動態代理和cglib動態代理想結合,通過判斷去創建對應的代理對象。

而不管是那種方法,最終執行完代理後,都會執行目標方法:method.invoke(target,agrs)–>傳入目標對象

所以執行A方法的代理後,執行A的目標方法,此時執行的對象是目標對象,所以目標對象執行A方法是A中隱藏的this

指的就是目標對象,即執行B方法的不再是代理對象而是目標對象,故B方法不會被代理

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: