日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态代理proxy与CGLib的区别

發(fā)布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态代理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;??
  • ??
  • /**?
  • ?*?定義一個賬戶接口?
  • ?*??
  • ?*?@author?Administrator?
  • ?*??
  • ?*/??
  • 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;??
  • ??
  • /**?
  • ?*?委托類(包含業(yè)務(wù)邏輯)?
  • ?*??
  • ?*?@author?Administrator?
  • ?*??
  • ?*/??
  • 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;??
  • ??
  • /**?
  • ?*?這是一個代理類(增強CountImpl實現(xiàn)類)?
  • ?*??
  • ?*?@author?Administrator?
  • ?*??
  • ?*/??
  • public?class?CountProxy?implements?Count?{??
  • ????private?CountImpl?countImpl;??
  • ??
  • ????/**?
  • ?????*?覆蓋默認構(gòu)造器?
  • ?????*??
  • ?????*?@param?countImpl?
  • ?????*/??
  • ????public?CountProxy(CountImpl?countImpl)?{??
  • ????????this.countImpl?=?countImpl;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?queryCount()?{??
  • ????????System.out.println("事務(wù)處理之前");??
  • ????????//?調(diào)用委托類的方法;??
  • ????????countImpl.queryCount();??
  • ????????System.out.println("事務(wù)處理之后");??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?updateCount()?{??
  • ????????System.out.println("事務(wù)處理之前");??
  • ????????//?調(diào)用委托類的方法;??
  • ????????countImpl.updateCount();??
  • ????????System.out.println("事務(wù)處理之后");??
  • ??
  • ????}??
  • ??
  • }??
  • 運行:

    [java]?view plaincopy
  • package?com.mahoutchina.pattern.proxy;??
  • ??
  • public?class?CountTest?{??
  • ??
  • ????/**?
  • ?????*?@param?args?
  • ?????*/??
  • ????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;??
  • ??
  • ????/**?
  • ?????*??
  • ?????*?@param?target?
  • ?????*?@return?
  • ?????*/??
  • ????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?{??
  • ??
  • /**?
  • ?*?@param?args?
  • ?*/??
  • 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;??
  • ??
  • /**?
  • ?*?這個是沒有實現(xiàn)接口的實現(xiàn)類?
  • ?*??
  • ?*?@author?student?
  • ?*??
  • ?*/??
  • 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;??
  • ??
  • /**?
  • ?*?使用cglib動態(tài)代理?
  • ?*??
  • ?*?@author?student?
  • ?*??
  • ?*/??
  • public?class?BookFacadeCglib?implements?MethodInterceptor?{??
  • ????private?Object?target;??
  • ??
  • ????/**?
  • ?????*?創(chuàng)建代理對象?
  • ?????*??
  • ?????*?@param?target?
  • ?????*?@return?
  • ?????*/??
  • ????public?Object?getInstance(Object?target)?{??
  • ????????this.target?=?target;??
  • ????????Enhancer?enhancer?=?new?Enhancer();??
  • ????????enhancer.setSuperclass(this.target.getClass());??
  • ????????//?回調(diào)方法??
  • ????????enhancer.setCallback(this);??
  • ????????//?創(chuàng)建代理對象??
  • ????????return?enhancer.create();??
  • ????}??
  • ??
  • ????@Override??
  • ????//?回調(diào)方法??
  • ????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)容還不錯,歡迎將生活随笔推薦給好友。