生活随笔
收集整理的這篇文章主要介紹了
动态代理proxy与CGLib的区别
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
轉(zhuǎn)載自?動態(tài)代理proxy與CGLib的區(qū)別
昨天被人問及動態(tài)代理與CGlib的區(qū)別,趕緊回顧一下:
什么是代理?靜態(tài)代理與動態(tài)代理靜態(tài)代理實例JDK動態(tài)代理實例CGLib 簡介CGLib 與JDK動態(tài)代理的區(qū)別
? ? 代理模式是Java中常見的一種模式,英文名字叫走Proxy或者Surrogate,代理的本意是一個人代表另一個人,或者一個機構(gòu)代表另一個機構(gòu),采取行動,因而,代理和現(xiàn)實生活中的中介有很大的類似,你買房子、賣房子,可以自己去操作,但是需要了解和買賣房產(chǎn)無關(guān)的細節(jié),如契稅等,而找一個中介,則不用關(guān)心這些與買賣房產(chǎn)無直接關(guān)系的中間細節(jié),只關(guān)心業(yè)務(wù)本身。
? ? ?因而,我們可以把代理模式的適用,總結(jié)為:代理類主要負責(zé)為委托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給委托類,以及事后處理消息等
? ?代理模式的用途,可以分為如下幾種:
? ? 1)遠程代理(Remote ):為遠程對象的invoke提供代理,典型的例子如RMI或者EJB,都會在本地生成一個遠程對象的stub。
? ? 2)虛擬代理(Virtual):如果需要創(chuàng)建一個資源消耗大的對象,則可以首先使用一個代理,使這個對象在需要時才真正創(chuàng)建。
? ? 3)Copy-On-Write 代理:把復(fù)制延遲到客戶端需要時才采取行動
? ? 4)保護(Protect)
? ? 5)Cache代理
? ?2.靜態(tài)代理與動態(tài)代理
代理分為靜態(tài)代理和動態(tài)代理
? ?按照代理創(chuàng)建的時期,可以分為動態(tài)代理和靜態(tài)代理:
?靜態(tài)代理:由程序員或者自動生成工具生成代理類,然后進行代理類的編譯和運行。在代理類、委托類運行之前,代理類已經(jīng)以.class的格式存在。
?動態(tài)代理:在程序運行時,由反射機制動態(tài)創(chuàng)建而成。
?3.靜態(tài)代理實例
? ? 靜態(tài)代理實例:
? ? ?首先需要一個接口:
[java]?view plaincopy
package?net.battier.dao;???????????public?interface?Count?{????????????public?void?queryCount();??????????????public?void?updateCount();????}??
? 然后是委托類,也就是接口的真正實現(xiàn)類,內(nèi)涵主要的業(yè)務(wù)邏輯:
[java]?view plaincopy
package?net.battier.dao.impl;????import?net.battier.dao.Count;???????????public?class?CountImpl?implements?Count?{????????@Override??????public?void?queryCount()?{??????????System.out.println("查看賬戶方法...");????????}????????@Override??????public?void?updateCount()?{??????????System.out.println("修改賬戶方法...");????????}????}??
? ?最后是代理類:
[java]?view plaincopy
CountProxy.java??package?net.battier.dao.impl;????import?net.battier.dao.Count;???????????public?class?CountProxy?implements?Count?{??????private?CountImpl?countImpl;??????????????????public?CountProxy(CountImpl?countImpl)?{??????????this.countImpl?=?countImpl;??????}????????@Override??????public?void?queryCount()?{??????????System.out.println("事務(wù)處理之前");????????????????????countImpl.queryCount();??????????System.out.println("事務(wù)處理之后");??????}????????@Override??????public?void?updateCount()?{??????????System.out.println("事務(wù)處理之前");????????????????????countImpl.updateCount();??????????System.out.println("事務(wù)處理之后");????????}????}??
運行:
[java]?view plaincopy
package?com.mahoutchina.pattern.proxy;????public?class?CountTest?{????????????????public?static?void?main(String[]?args)?{??????????CountImpl?countImpl?=?new?CountImpl();????????????CountProxy?countProxy?=?new?CountProxy(countImpl);????????????countProxy.updateCount();????????????countProxy.queryCount();?????????}????}??
? 從靜態(tài)代理中可以看出:
? ? 1.接口:代理類需要實現(xiàn)一個接口,這個接口和委托類的接口是一樣的,這樣proxy才能和委托類行為表現(xiàn)一致
? ? 2. 方法(Method):由于接口限制,proxy類中也要有interface中的各個方法,這就造成了代碼重復(fù)
? ?
4.JDK動態(tài)代理實例
? ??動態(tài)代理類克服了proxy需要繼承專一的interface接口,并且要實現(xiàn)相應(yīng)的method的缺陷。從JDK 1.3以來,Java 語言通過java.lang.reflex庫提供的三個類直接支持代理:
? ? ?java.lang.reflect.Proxy,java.lang.reflect.InvocationHandler 和Method.
? ? Proxy類在運行時動態(tài)創(chuàng)建代理對象,這也是dynamic proxy的由來,下面是類圖,其中最重要的是newProxyInstance,這個方法中,指明了將要代理的類的加載器,業(yè)務(wù)類接口,以及代理類要執(zhí)行動作的調(diào)用處理器(InvokeHandler)
?
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,?
InvocationHandler h)?
?????????????????????????????? throws IllegalArgumentException?
參數(shù)說明:?
ClassLoader loader:類加載器?
Class<?>[] interfaces:得到全部的接口?
InvocationHandler h:得到InvocationHandler接口的子類實例?
Ps:類加載器?
在Proxy類中的newProxyInstance()方法中需要一個ClassLoader類的實例,ClassLoader實際上對應(yīng)的是類加載器,在Java中主要有一下三種類加載器;?
Booststrap ClassLoader:此加載器采用C++編寫,一般開發(fā)中是看不到的;?
Extendsion ClassLoader:用來進行擴展類的加載,一般對應(yīng)的是jre\lib\ext目錄中的類;?
AppClassLoader:(默認)加載classpath指定的類,是最常使用的是一種加載器。?
? ?當(dāng)系統(tǒng)有了一個代理對象之后,對原方法的調(diào)用會首先被分派到一個調(diào)用處理器(Invocation Handler).InvocationHandler 接口如下圖所示:
? ??
? 代碼:
? ? 接口:
[java]?view plaincopy
package?com.mahoutchina.pattern.proxy.dynamicproxy;????public?interface?BookFacade?{??????public?void?addBook();??????public?void?deleteBook();??}??
? 實際業(yè)務(wù)類:
[java]?view plaincopy
package?com.mahoutchina.pattern.proxy.dynamicproxy;????public?class?BookFacadeImpl?implements?BookFacade?{????????@Override??????public?void?addBook()?{??????????System.out.println("add?book?logic?is?running。。。");???????}????????@Override??????public?void?deleteBook()?{??????????System.out.println("delete?book?logic?is?running。。。");????????????????}??????????}??
? 動態(tài)代理類:
[java]?view plaincopy
package?com.mahoutchina.pattern.proxy.dynamicproxy;????import?java.lang.reflect.InvocationHandler;??import?java.lang.reflect.Method;??import?java.lang.reflect.Proxy;????public?class?BookFacadeProxy?implements?InvocationHandler?{??????private?Object?target;??????????????????public?Object?bind(Object?target)?{??????????this.target?=?target;????????????????????return?Proxy.newProxyInstance(target.getClass().getClassLoader(),??????????????????target.getClass().getInterfaces(),?this);??????}????????@Override??????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)??????????????throws?Throwable?{??????????Object?result=null;??????????System.out.println("Proxy?start...");??????????System.out.println("method?name:"+method.getName());??????????result=method.invoke(target,?args);??????????System.out.println("Proxy?end...");??????????return?result;??????}????}??
? 測試類:
[java]?view plaincopy
package?com.mahoutchina.pattern.proxy.dynamicproxy;????ublic?class?TestProxy?{????????public?static?void?main(String[]?args)?{??????BookFacadeProxy?proxy?=?new?BookFacadeProxy();??????BookFacade?bookProxy?=?(BookFacade)?proxy.bind(new?BookFacadeImpl());??????bookProxy.addBook();??????bookProxy.deleteBook();??}??
??
?對于JDK 的Proxy,有以下幾點:
? ? 1)Interface:對于JDK proxy,業(yè)務(wù)類是需要一個Interface的,這也是一個缺陷
? ? 2)Proxy,Proxy 類是動態(tài)產(chǎn)生的,這個類在調(diào)用Proxy.newProxyInstance(targetCls.getClassLoader, targetCls.getInterface,InvocationHander)之后,會產(chǎn)生一個Proxy類的實例。實際上這個Proxy類也是存在的,不僅僅是類的實例。這個Proxy類可以保存到硬盤上。
? ? 3) Method:對于業(yè)務(wù)委托類的每個方法,現(xiàn)在Proxy類里面都不用靜態(tài)顯示出來
? ? 4) InvocationHandler: 這個類在業(yè)務(wù)委托類執(zhí)行時,會先調(diào)用invoke方法。invoke方法再執(zhí)行相應(yīng)的代理操作,可以實現(xiàn)對業(yè)務(wù)方法的再包裝
? ? 5?CGLib 簡介
? ? ? ? ??JDK的動態(tài)代理機制只能代理實現(xiàn)了接口的類,而不能實現(xiàn)接口的類就不能實現(xiàn)JDK的動態(tài)代理,cglib是針對類來實現(xiàn)代理的,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。?
示例?
? ?業(yè)務(wù)類:
[java]?view plaincopy
package?net.battier.dao;????public?interface?BookFacade?{??????public?void?addBook();??}??
?
?
[java]?view plaincopy
package?net.battier.dao.impl;???????????public?class?BookFacadeImpl1?{??????public?void?addBook()?{??????????System.out.println("增加圖書的普通方法...");??????}??}??
? 代理:
[java]?view plaincopy
package?net.battier.proxy;????import?java.lang.reflect.Method;????import?net.sf.cglib.proxy.Enhancer;??import?net.sf.cglib.proxy.MethodInterceptor;??import?net.sf.cglib.proxy.MethodProxy;???????????public?class?BookFacadeCglib?implements?MethodInterceptor?{??????private?Object?target;???????????????????public?Object?getInstance(Object?target)?{??????????this.target?=?target;??????????Enhancer?enhancer?=?new?Enhancer();??????????enhancer.setSuperclass(this.target.getClass());????????????????????enhancer.setCallback(this);????????????????????return?enhancer.create();??????}????????@Override????????????public?Object?intercept(Object?obj,?Method?method,?Object[]?args,??????????????MethodProxy?proxy)?throws?Throwable?{??????????System.out.println("事物開始");??????????proxy.invokeSuper(obj,?args);??????????System.out.println("事物結(jié)束");??????????return?null;??????????}????}??
? 測試;
[java]?view plaincopy
package?net.battier.test;????import?net.battier.dao.impl.BookFacadeImpl1;??import?net.battier.proxy.BookFacadeCglib;????public?class?TestCglib?{????????????public?static?void?main(String[]?args)?{??????????BookFacadeCglib?cglib=new?BookFacadeCglib();??????????BookFacadeImpl1?bookCglib=(BookFacadeImpl1)cglib.getInstance(new?BookFacadeImpl1());??????????bookCglib.addBook();??????}??}??
總結(jié)
以上是生活随笔為你收集整理的动态代理proxy与CGLib的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。