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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态代理proxy与CGLib的区别

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态代理proxy与CGLib的区别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自?動態代理proxy與CGLib的區別

昨天被人問及動態代理與CGlib的區別,趕緊回顧一下:

  • 什么是代理?
  • 靜態代理與動態代理
  • 靜態代理實例
  • JDK動態代理實例
  • CGLib 簡介
  • CGLib 與JDK動態代理的區別
  • ? ? 代理模式是Java中常見的一種模式,英文名字叫走Proxy或者Surrogate,代理的本意是一個人代表另一個人,或者一個機構代表另一個機構,采取行動,因而,代理和現實生活中的中介有很大的類似,你買房子、賣房子,可以自己去操作,但是需要了解和買賣房產無關的細節,如契稅等,而找一個中介,則不用關心這些與買賣房產無直接關系的中間細節,只關心業務本身。

    ? ? ?因而,我們可以把代理模式的適用,總結為:代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事后處理消息等

    ? ?代理模式的用途,可以分為如下幾種:

    ? ? 1)遠程代理(Remote ):為遠程對象的invoke提供代理,典型的例子如RMI或者EJB,都會在本地生成一個遠程對象的stub。

    ? ? 2)虛擬代理(Virtual):如果需要創建一個資源消耗大的對象,則可以首先使用一個代理,使這個對象在需要時才真正創建。

    ? ? 3)Copy-On-Write 代理:把復制延遲到客戶端需要時才采取行動

    ? ? 4)保護(Protect)

    ? ? 5)Cache代理

    ? ?2.靜態代理與動態代理

    代理分為靜態代理和動態代理

    ? ?按照代理創建的時期,可以分為動態代理和靜態代理:

    ?靜態代理:由程序員或者自動生成工具生成代理類,然后進行代理類的編譯和運行。在代理類、委托類運行之前,代理類已經以.class的格式存在。

    ?動態代理:在程序運行時,由反射機制動態創建而成。


    ?3.靜態代理實例

    ? ? 靜態代理實例:

    ? ? ?首先需要一個接口:

    [java]?view plaincopy
  • package?net.battier.dao;??
  • ??
  • /**?
  • ?*?定義一個賬戶接口?
  • ?*??
  • ?*?@author?Administrator?
  • ?*??
  • ?*/??
  • public?interface?Count?{??
  • ????//?查看賬戶方法??
  • ????public?void?queryCount();??
  • ??
  • ????//?修改賬戶方法??
  • ????public?void?updateCount();??
  • ??
  • }??
  • ? 然后是委托類,也就是接口的真正實現類,內涵主要的業務邏輯: [java]?view plaincopy
  • package?net.battier.dao.impl;??
  • ??
  • import?net.battier.dao.Count;??
  • ??
  • /**?
  • ?*?委托類(包含業務邏輯)?
  • ?*??
  • ?*?@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實現類)?
  • ?*??
  • ?*?@author?Administrator?
  • ?*??
  • ?*/??
  • public?class?CountProxy?implements?Count?{??
  • ????private?CountImpl?countImpl;??
  • ??
  • ????/**?
  • ?????*?覆蓋默認構造器?
  • ?????*??
  • ?????*?@param?countImpl?
  • ?????*/??
  • ????public?CountProxy(CountImpl?countImpl)?{??
  • ????????this.countImpl?=?countImpl;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?queryCount()?{??
  • ????????System.out.println("事務處理之前");??
  • ????????//?調用委托類的方法;??
  • ????????countImpl.queryCount();??
  • ????????System.out.println("事務處理之后");??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?updateCount()?{??
  • ????????System.out.println("事務處理之前");??
  • ????????//?調用委托類的方法;??
  • ????????countImpl.updateCount();??
  • ????????System.out.println("事務處理之后");??
  • ??
  • ????}??
  • ??
  • }??
  • 運行:

    [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();???
  • ??
  • ????}??
  • ??
  • }??
  • ? 從靜態代理中可以看出:

    ? ? 1.接口:代理類需要實現一個接口,這個接口和委托類的接口是一樣的,這樣proxy才能和委托類行為表現一致

    ? ? 2. 方法(Method):由于接口限制,proxy類中也要有interface中的各個方法,這就造成了代碼重復

    ? ?

    4.JDK動態代理實例
    ? ??
    動態代理類克服了proxy需要繼承專一的interface接口,并且要實現相應的method的缺陷。從JDK 1.3以來,Java 語言通過java.lang.reflex庫提供的三個類直接支持代理:

    ? ? ?java.lang.reflect.Proxy,java.lang.reflect.InvocationHandler 和Method.

    ? ? Proxy類在運行時動態創建代理對象,這也是dynamic proxy的由來,下面是類圖,其中最重要的是newProxyInstance,這個方法中,指明了將要代理的類的加載器,業務類接口,以及代理類要執行動作的調用處理器(InvokeHandler)


    ?

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,?
    InvocationHandler h)?
    ?????????????????????????????? throws IllegalArgumentException?
    參數說明:?
    ClassLoader loader:類加載器?
    Class<?>[] interfaces:得到全部的接口?
    InvocationHandler h:得到InvocationHandler接口的子類實例?

    Ps:類加載器?
    在Proxy類中的newProxyInstance()方法中需要一個ClassLoader類的實例,ClassLoader實際上對應的是類加載器,在Java中主要有一下三種類加載器;?
    Booststrap ClassLoader:此加載器采用C++編寫,一般開發中是看不到的;?
    Extendsion ClassLoader:用來進行擴展類的加載,一般對應的是jre\lib\ext目錄中的類;?
    AppClassLoader:(默認)加載classpath指定的類,是最常使用的是一種加載器。?

    ? ?當系統有了一個代理對象之后,對原方法的調用會首先被分派到一個調用處理器(Invocation Handler).InvocationHandler 接口如下圖所示:

    ? ??

    ? 代碼:

    ? ? 接口:

    [java]?view plaincopy
  • package?com.mahoutchina.pattern.proxy.dynamicproxy;??
  • ??
  • public?interface?BookFacade?{??
  • ????public?void?addBook();??
  • ????public?void?deleteBook();??
  • }??
  • ? 實際業務類: [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。。。");??
  • ??????????
  • ????}??
  • ??????
  • ??
  • }??
  • ? 動態代理類: [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,業務類是需要一個Interface的,這也是一個缺陷

    ? ? 2)Proxy,Proxy 類是動態產生的,這個類在調用Proxy.newProxyInstance(targetCls.getClassLoader, targetCls.getInterface,InvocationHander)之后,會產生一個Proxy類的實例。實際上這個Proxy類也是存在的,不僅僅是類的實例。這個Proxy類可以保存到硬盤上。

    ? ? 3) Method:對于業務委托類的每個方法,現在Proxy類里面都不用靜態顯示出來

    ? ? 4) InvocationHandler: 這個類在業務委托類執行時,會先調用invoke方法。invoke方法再執行相應的代理操作,可以實現對業務方法的再包裝

    ? ? 5?CGLib 簡介

    ? ? ? ? ??JDK的動態代理機制只能代理實現了接口的類,而不能實現接口的類就不能實現JDK的動態代理,cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。?
    示例?

    ? ?業務類:

    [java]?view plaincopy
  • package?net.battier.dao;??
  • ??
  • public?interface?BookFacade?{??
  • ????public?void?addBook();??
  • }??
  • ? ? [java]?view plaincopy
  • package?net.battier.dao.impl;??
  • ??
  • /**?
  • ?*?這個是沒有實現接口的實現類?
  • ?*??
  • ?*?@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動態代理?
  • ?*??
  • ?*?@author?student?
  • ?*??
  • ?*/??
  • public?class?BookFacadeCglib?implements?MethodInterceptor?{??
  • ????private?Object?target;??
  • ??
  • ????/**?
  • ?????*?創建代理對象?
  • ?????*??
  • ?????*?@param?target?
  • ?????*?@return?
  • ?????*/??
  • ????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("事物結束");??
  • ????????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();??
  • ????}??
  • }??

  • 總結

    以上是生活随笔為你收集整理的动态代理proxy与CGLib的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。