基于jdk動態(tài)代理和cglib動態(tài)代理實(shí)現(xiàn)及區(qū)別說明
jdk動態(tài)代理和cglib動態(tài)代理實(shí)現(xiàn)及區(qū)別
代理模式是一種設(shè)計(jì)模式,提供了對目標(biāo)對象額外的訪問方式,即通過代理對象訪問目標(biāo)對象,這樣可以在不修改原目標(biāo)對象的前提下,提供額外的功能操作,擴(kuò)展目標(biāo)對象的功能。
代理模式又分為:
- 靜態(tài)代理
- jdk動態(tài)代理
- cglib動態(tài)代理
- 由于靜態(tài)代理會產(chǎn)生過多的代理類,一旦接口增加方法,目標(biāo)對象與代理對象都要進(jìn)行修改,不易維護(hù)。
- 而動態(tài)代理是動態(tài)地在內(nèi)存中構(gòu)建代理對象,從而實(shí)現(xiàn)對目標(biāo)對象的代理功能,接口增加方法時(shí)代理對象不受影響 。
下面我們講講jdk動態(tài)代理和cglib動態(tài)代理實(shí)現(xiàn)及區(qū)別
jdk動態(tài)代理實(shí)現(xiàn)
@Test public void test(){ ? ? IPerson target = new ManPerson(); ? ? IPerson proxy = (IPerson)Proxy.newProxyInstance( ? ? ? ? target.getClass().getClassLoader(),? ? ? ? ? target.getClass().getInterfaces(),? ? ? ? ? new PersonInvocationHandler(target)); ? ? proxy.eat(); ? ? proxy.sleep(); } // 代理對象 class PersonInvocationHandler implements InvocationHandler{ ? ? private Object target; ? ? public PersonInvocationHandler(Object target){ ? ? ? ? this.target = target; ? ? } ? ? @Override ? ? public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ ? ? ? ? System.out.println("start"); ?? ?Object result = method.invoke(target, args); ?? ?System.out.println("end"); ?? ?return result; ? ? } } // 目標(biāo)對象 class ManPerson implements IPerson{ ? ? @Override ? ? public void eat(){ ?? ?System.out.println("吃飯中......"); ? ? } ? ? @Override ? ? public void sleep(){ ?? ?System.out.println("睡覺中......"); ? ? } } // 目標(biāo)對象接口 interface IPerson{ ? ? void eat(); ? ? void sleep(); }
cglib動態(tài)代理
@Test public void test(){ ? ? Person proxy = (Person)Enhancer.create(Person.class, new PersonMethodInterceptor()); ? ? proxy.eat(); ? ? proxy.sleep(); } // 代理對象 class PersonMethodInterceptor implements MethodInterceptor{ ? ? @Override ? ? public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable{ ? ? ? ? System.out.println("start"); ?? ?Object result = methodProxy.invokeSuper(o, objects); ?? ?System.out.println("end"); ?? ?return result; ? ? } }
目標(biāo)對象
public class Person{ ? ? public void eat(){ ?? ?System.out.println("吃飯中......"); ? ? } ? ? public void sleep(){ ?? ?System.out.println("睡覺中......"); ? ? } }
區(qū)別
1.JDK動態(tài)代理是實(shí)現(xiàn)了被代理對象的接口,Cglib是繼承了被代理對象。
2.JDK和Cglib都是在運(yùn)行期生成字節(jié)碼,JDK是直接寫Class字節(jié)碼,Cglib使用ASM框架寫Class字節(jié)碼,Cglib代理實(shí)現(xiàn)更復(fù)雜,生成代理類比JDK效率低。
3.JDK調(diào)用代理方法,是通過反射機(jī)制調(diào)用,Cglib是通過FastClass機(jī)制直接調(diào)用方法,Cglib執(zhí)行效率更高。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot 項(xiàng)目發(fā)布到 Tomcat 服務(wù)器的操作步驟
這篇文章主要介紹了Spring Boot 項(xiàng)目發(fā)布到 Tomcat 服務(wù)器的操作步驟,需要的朋友可以參考下2017-04-04Java中Runnable和Callable分別什么時(shí)候使用
提到 Java 就不得不說多線程了,就算你不想說,面試官也得讓你說呀,那說到線程,就不得不說Runnable和Callable這兩個(gè)家伙了,二者在什么時(shí)候使用呢,下面就來和簡單講講2023-08-08Spring Boot整合JPA使用多個(gè)數(shù)據(jù)源的方法步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot整合JPA使用多個(gè)數(shù)據(jù)源的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08關(guān)于mybatis-plus-generator的簡單使用示例詳解
在springboot項(xiàng)目中集成mybatis-plus是很方便開發(fā)的,最近看了一下plus的文檔,簡單用一下它的代碼生成器,接下來通過實(shí)例代碼講解關(guān)于mybatis-plus-generator的簡單使用,感興趣的朋友跟隨小編一起看看吧2024-03-03springboot實(shí)現(xiàn)攔截器之驗(yàn)證登錄示例
本篇文章主要介紹了springboot實(shí)現(xiàn)攔截器之驗(yàn)證登錄示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02