面試系列~動(dòng)態(tài)代理實(shí)現(xiàn)與原理

動(dòng)態(tài)代理有JDK動(dòng)態(tài)代理, CGLIB動(dòng)態(tài)代理, SpringAOP動(dòng)態(tài)代理

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

?jdk動(dòng)態(tài)代理采用的是字節(jié)碼重組的方式實(shí)現(xiàn)的, 即重新生成一個(gè)對(duì)象來代替原來的對(duì)象, 它的實(shí)現(xiàn)原理如下:
??(1)通過反射獲取被代理對(duì)象, 以及它的所有的接口的引用
??(2)動(dòng)態(tài)生成java源代碼, 在代碼中加入需要增強(qiáng)的邏輯并且調(diào)用被代理類的方法, 同時(shí)新的類要實(shí)現(xiàn)被代理類實(shí)現(xiàn)的所有接口, 由(1)中獲取的就可以編寫
??(3)編譯動(dòng)態(tài)生成的.java文件, 從而生成.class文件
??(4)將.class文件通過ClassLoader加載到JVM中運(yùn)行

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

??(1)生成階段, 把被代理類當(dāng)做interface, 通過反射和類加載生成代理類
??(2)執(zhí)行階段, 當(dāng)執(zhí)行到methodProxy.invokeSuper()方法時(shí), 會(huì)為代理類和被代理類各生成一個(gè)FastClass類, (一共生成了3個(gè)類, 這個(gè)過程比JDK動(dòng)態(tài)代理慢 ) 并且還會(huì)為代理類和被代理類的方法分配一個(gè)index,然后將FastClass放入緩存, 下次判斷不為null時(shí)直接取出來使用
??(3)把(2)中的index當(dāng)做一個(gè)參數(shù)進(jìn)行使用, FastClass機(jī)制就能夠很快定位到要調(diào)用的方法,而不是通過反射去調(diào)用方法, 這個(gè)過程比JDK動(dòng)態(tài)代理快

CGLIB動(dòng)態(tài)代理與JDK動(dòng)態(tài)代理比較

??(1)JDK動(dòng)態(tài)代理需被代理類實(shí)現(xiàn)接口, 同時(shí)代理類實(shí)現(xiàn)的是接口, CGLIB動(dòng)態(tài)代理不需要被代理類實(shí)現(xiàn)任何接口, 同時(shí)代理類是繼承被代理類(當(dāng)然相同的方法是重寫了, 調(diào)用過程是先調(diào)用被代理的方法, 然后被攔截器攔截, 然后執(zhí)行super的方法)
??(2)JDK 動(dòng)態(tài)代理和 CGLIB動(dòng)態(tài)代理都在運(yùn)行期生成字節(jié)碼,但是JDK是直接寫字節(jié)碼, CGLIB使用的ASM框架(比較復(fù)雜我也沒有研究透) 所有CGLIB動(dòng)態(tài)代理生成代理類的效率比JDK動(dòng)態(tài)代理慢
??(3)CGLIB動(dòng)態(tài)代理使用的FastClass機(jī)制執(zhí)行, 比JDK動(dòng)態(tài)代理使用反射執(zhí)行快一些

三SpringAOP

??Spring就是利用以上兩種動(dòng)態(tài)代理原理實(shí)現(xiàn)的AOP
??(1)當(dāng)Bean有實(shí)現(xiàn)接口的情況, Spring使用的是JDK動(dòng)態(tài)代理來實(shí)現(xiàn)AOP
??(2)當(dāng)Bean沒有實(shí)現(xiàn)接口的情況, Spring使用CGLIB代理來實(shí)現(xiàn)AOP

?著作權(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ù)。

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

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