Aop選型實測

https://javatar.iteye.com/blog/814426

參考Dubbo的選型實踐

  • Jdk動態(tài)代理

使用Component.DynamicProxyPerformanceTest輸出動態(tài)代理class文件,使用javap -c觀察字節(jié)碼,使用jdGui或Luyten反編譯工具查看反編譯出的源碼(更清晰明了,無需去看字節(jié)碼)

//為什么動態(tài)代理只能代理接口?因為生成的代理類繼承了Proxy,無法再繼承其他類
public final class $proxy0 extends Proxy implements CountService
{
    private static Method m1;
    private static Method m3;
    static {
        try {
            //通過反射獲取當(dāng)前接口以及Object對象的所有方法(含未列出的hashCode()等)
            $proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            $proxy0.m3 = Class.forName("aop.CountService").getMethod("count", (Class<?>[])new Class[0]);
        }
    }
    public final boolean equals(final Object o) {
        //super.h為父類Proxy.InvocationHandler字段
        //調(diào)用其invoke方法
        return (boolean)super.h.invoke(this, $proxy0.m1, new Object[] { o });
    }
    public final int count() {
        return (int)super.h.invoke(this, $proxy0.m3, null);
    }
}

所以說,jdk動態(tài)代理使用字節(jié)碼技術(shù)創(chuàng)建代理類,代理類中通過反射獲取原始方法method并調(diào)用自定義的InvocationHandler

  • ASM
//通過classWriter寫字節(jié)碼然后轉(zhuǎn)換為字節(jié)數(shù)組
byte[] code = classWriter.toByteArray();
//通過Jdk.ClassLoader實例的方法根據(jù)字節(jié)碼數(shù)組創(chuàng)建class
ClassLoader.defineClass(name, code, 0, code.length);

asm pom依賴已經(jīng)改成了org.ow2.asm

  • Cglib

cglib是在asm基礎(chǔ)上進行的封裝,pom包含了asm的依賴,所以測試asm無需單獨再依賴asm

//該設(shè)置用于輸出cglib動態(tài)代理產(chǎn)生的類
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");

選型分析

Jdk,Cglib,JavassistProxy創(chuàng)建出來的代理類包含equals()和hashCode()等Object對象原生方法,JavassistByte和ASM不含
測試發(fā)現(xiàn),直接調(diào)用CountService.count()的性能是使用反射調(diào)用method.invoke(CountServic)的2-4倍
Jdk,Cglib,JavassistProxy在回調(diào)函數(shù)中暴露Method,Jdk,JavassistProxy直接通過反射調(diào)用,Cglib通過MethodProxy調(diào)用
JavassistByte通過字符串形式的代碼創(chuàng)建class,ASM通過ClassWriter直接寫入字節(jié)碼創(chuàng)建class,創(chuàng)建后直接調(diào)用CountService.count(),不使用反射

測試結(jié)果:
NoProxy>ASM=JavassistByte>Cglib>Jdk>JavassistProxy,考慮使用方便,優(yōu)先使用JavassistByte
ASM和JavassistByte大約比無Proxy調(diào)用慢10%左右,是后面3者的2~3倍,直覺認(rèn)為主要差別在于字節(jié)碼class函數(shù)直接調(diào)用和后面3者method反射調(diào)用

  • SpringAop

根據(jù)Spring的官方文檔,性能不是選擇使用Jdk或Cglib的重要因素

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容