5分鐘弄懂動(dòng)態(tài)代理

代理模式

用途:控制對(duì)象的訪問,或者增強(qiáng)對(duì)象功能
簡(jiǎn)單來說就是代理對(duì)象通過組合的方式獲得被代理對(duì)象,且實(shí)現(xiàn)相同接口。在執(zhí)行接口方法時(shí),增加一些操作,并調(diào)用被代理對(duì)象的方法。
代理模式分為靜態(tài)代理和動(dòng)態(tài)代理。靜態(tài)代理是程序員手動(dòng)編寫代理類,動(dòng)態(tài)代理則是在程序運(yùn)行期間動(dòng)態(tài)生成代理類。由于靜態(tài)代理違反了開閉原則,所以需要引入動(dòng)態(tài)代理。

動(dòng)態(tài)代理

動(dòng)態(tài)代理有兩種實(shí)現(xiàn)方式,一種是JDK方式,一種是CGLIB方式。

JDK方式

核心是java.lang.reflect中的Proxy類,和InvocationHandler接口。

一般使用流程是程序員通過注解標(biāo)記需要被代理的類,之后框架在處理注解時(shí)通過Proxy類中的newProxyInstance靜態(tài)方法生成代理類的對(duì)象(在內(nèi)存中先生成字節(jié)碼文件,再生成對(duì)象)。

   public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException

該方法有三個(gè)參數(shù):
loader是被代理類的類加載器,用來確認(rèn)當(dāng)前的代理緩存上下文。(如果已經(jīng)有代理類,不會(huì)重新生成)
interfaces是被代理類實(shí)現(xiàn)的接口。
h 就是實(shí)現(xiàn)了InvocationHandler的對(duì)象,其通過重新InvocationHandler對(duì)象的Invoke方法表明特定的增強(qiáng)操作(如事務(wù))。

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

生成的代理對(duì)象會(huì)替代被代理對(duì)象來執(zhí)行對(duì)應(yīng)的方法。

示例 可參考SrpingAop中實(shí)現(xiàn)InvocationHandler的對(duì)象org.springframework.aop.framework.JdkDynamicAopProxy.class

CGLIB方式

CGLIB主要解決JDK動(dòng)態(tài)代理只能對(duì)接口實(shí)現(xiàn)類進(jìn)行代理的問題。主要用字節(jié)碼動(dòng)態(tài)編輯的方式生成被代理類的子類對(duì)象作為代理類。

CGLIB 原理:動(dòng)態(tài)生成一個(gè)要代理類的子類,子類重寫要代理的類的所有不是final的方法。在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用,順勢(shì)織入橫切邏輯。它比使用java反射的JDK動(dòng)態(tài)代理要快。
CGLIB 底層:使用字節(jié)碼處理框架ASM,來轉(zhuǎn)換字節(jié)碼并生成新的類。不鼓勵(lì)直接使用ASM,因?yàn)樗竽惚仨殞?duì)JVM內(nèi)部結(jié)構(gòu)包括class文件的格式和指令集都很熟悉。
CGLIB缺點(diǎn):對(duì)于final方法,無法進(jìn)行代理。

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

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