免费看欧美黑人毛片-免费看毛片网站-免费看毛片的网站-免费看久久-中文字幕日韩欧美-中文字幕日韩精品一区

您現在的位置:首頁 > IT認證 > JAVA >

Java基礎知識:Java動態代理


沒事的時候翻看lang.reflect包下的代碼,發現有兩部分內容:涉及反射和動態代理。

    很多地方都可以看到動態代理的影子,只是一直沒仔細看下。

    在學習之前,先提出幾個問題,帶著問題來看代碼:

    1.什么是動態代理?

    2.為什么使用動態代理?

    3.使用它有哪些好處?

    4.哪些地方需要動態代理?

    熟悉設計模式的人對于代理模式可 能都不陌生。 代理對象和被代理對象一般實現相同的接口,調用者與代理對象進行交互。代理的存在對于調用者來說是透明的,調用者看到的只是接口。代理對象則可以封裝一些內部的處理邏輯,如訪問控制、遠程通信、日志、緩存等。比如一個對象訪問代理就可以在普通的訪問機制之上添加緩存的支持。這種模式在RMI和EJB中都得到了廣泛的使用。傳統的代理模式的實現,需要在源代碼中添加一些附加的類。這些類一般是手寫或是通過工具來自動生成。JDK 5引入的動態代理機制,允許開發人員在運行時刻動態的創建出代理類及其對象。在運行時刻,可以動態創建出一個實現了多個接口的代理類。每個代理類的對象都會關聯一個表示內部處理邏輯的InvocationHandler接 口的實現。當使用者調用了代理對象所代理的接口中的方法的時候,這個調用的信息會被傳遞給InvocationHandler的invoke方法。在 invoke方法的參數中可以獲取到代理對象、方法對應的Method對象和調用的實際參數。invoke方法的返回值被返回給使用者。這種做法實際上相 當于對方法調用進行了攔截。熟悉AOP的人對這種使用模式應該不陌生。但是這種方式不需要依賴AspectJ等AOP框架。

    動態代理可以提供對另一個對象的訪問,同時隱藏實際對象的具體事實,代理對象對客戶隱藏了實際對象。動態代理可以對請求進行其他的一些處理,在不允許直接訪問某些類,

    或需要對訪問做一些特殊處理等,這時候可以考慮使用代理。目前 Java 開發包中提供了對動態代理的支持,但現在只支持對接口的實現。

    主要是通過 ng.reflect.Proxy 類和 ng.reflect.InvocationHandler 接口。 Proxy 類主要用來獲取動態代理對象,InvocationHandler 接口用來約束調用者行為。

    "寫一個 ArrayList 類的代理,其內部實現和 ArrayList 中完全相同的功能,并可以計算每個方法運行的時間。"這是一份考題上的題目,沒有答案,來看下實現:

    [java]

    package proxy;

    import ng.reflect.InvocationHandler;

    import thod;

    import ng.reflect.Proxy;

    import java.util.ArrayList;

    import java.util.List;

    import ncurrent.TimeUnit;

    public class ProxyApp {

    public static void main(String[] args){ //ArrayList代理,通過代理計算每個方法調用所需時間

    List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(

    ArrayList.class.getClassLoader(),   /*定義代理類的類加載器,用于創建代理對象,不一定必須是ArrayList,也可以是其他的類加載器*/

    ArrayList.class.getInterfaces(),     /*代理類要實現的接口列表*/

    new InvocationHandler() {            /*指派方法調用的調用處理程序,這里用了匿名內部類*/

    private ArrayList<Integer> target = new ArrayList<Integer>(); //目標對象(真正操作的對象)

    /**

    * <B>方法描述:</B>

    * <p style="margin-left:20px;color:#A52A2A;">

    * 在代理實例上處理方法調用并返回結果

    * @param proxy     代理對象(注意不是目標對象)

    * @param method  被代理的方法

    * @param args         被代理的方法的參數集

    * @return <span style="color: #008080;"> 返回方法調用結果 </span>

    */

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    long beginTime = System.currentTimeMillis();  //開始時間

    TimeUnit.MICROSECONDS.sleep(1);

    Object obj = method.invoke(target, args);          //實際調用的方法,并接受方法的返回值

    long endTime = System.currentTimeMillis();   //結束時間

    System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");

    return obj;   //返回實際調用的方法的返回值

    }

    }

    );

    arrayListProxy.add(2);

    arrayListProxy.add(4);

    System.out.println("--------- 迭代 ---------");

    for(int i : arrayListProxy){

    System.out.print(i + "t");

    }

    }

    }從代碼上來看,用到了匿名內部類,這樣一來,InvocationHandler 只能用一次,如果多個地方都需要用到這樣一個相同的 InvocationHandler,可以將其抽象出來成為一個單獨的類:

    [java]

    package test;

    import ng.reflect.InvocationHandler;

    import thod;

    import ncurrent.TimeUnit;

    public class MyInvocationHandler implements InvocationHandler{

    private Object target; //目標對象

    public MyInvocationHandler(Object target){

    this.target = target;

    }

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    long beginTime = System.currentTimeMillis();

    TimeUnit.MICROSECONDS.sleep(1);

    Object obj = method.invoke(target, args);

    long endTime = System.currentTimeMillis();

    System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");

    return obj;

    }

    }

    客戶端調用改成:

    [java]

    package example;

    import ng.reflect.Proxy;

    import java.util.ArrayList;

    import java.util.List;

    /**

    * -----------------------------------------

    * -----------------------------------------

    */

    public class ProxyApp {

    public static void main(String[] args){

    //ArrayList代理,通過代理計算每個方法調用所需時間

    List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(

    ArrayList.class.getClassLoader(),     /*定義代理類的類加載器,用于創建代理對象,不一定必須是ArrayList,也可以是其他的類加載器*/

    ArrayList.class.getInterfaces(),       /*代理類要實現的接口列表*/

    new MyInvocationHandler(new ArrayList<Integer>())         /*指派方法調用的調用處理程序,這里用了匿名內部類*/

    );

    arrayListProxy.add(2);

    arrayListProxy.add(4);

    System.out.println("--------- 迭代 ---------");

    for(int i : arrayListProxy){

    System.out.print(i + "t");

    }

    }

    }從上面代碼看來,客戶端知道代理的實際目標對象,還知道怎么樣去創建這樣一個代理對象,如果想把這些信息全部對客戶端隱藏起來,可以將這些代碼挪到一個類中,將它們封裝起來:

    [java]

    package example;

    import ng.reflect.InvocationHandler;

    import thod;

    import ng.reflect.Proxy;

    import java.util.ArrayList;

    import java.util.List;

    import ncurrent.TimeUnit;

    /**

    * -----------------------------------------

    * -----------------------------------------

    */

    public class ProxyUtil {

    public enum ArrayListProxy {

    PROXY;

    private Object target;

    ArrayListProxy(){

    this.target = new ArrayList<Object>();

    }

    public List getInstance(){

    return (List)Proxy.newProxyInstance(ArrayList.class.getClassLoader(), ArrayList.class.getInterfaces(),

    new InvocationHandler() {

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    long beginTime = System.currentTimeMillis();

    TimeUnit.MICROSECONDS.sleep(1);

    Object obj = method.invoke(target, args);

    long endTime = System.currentTimeMillis();

    System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");

    return obj;

    }

    });

    }

    }

    }

    客戶端調用改成:

    package example;

    import java.util.List;

    import example.ProxyUtil.ArrayListProxy;

    /**

    * -----------------------------------------

    ------------------

    */

    public class ProxyApp {

    public static void main(String[] args){

    List<Integer> arrayListProxy = ArrayListProxy.PROXY.getInstance();

    arrayListProxy.add(2);

    arrayListProxy.add(4);

    System.out.println("--------- 迭代 ---------");

    for(int i : arrayListProxy){

    System.out.print(i + "t");

    }

    }

    }

    上面代碼中用到了枚舉 enum,如果不想用枚舉,就改用普通類來實現就行了。

    總結:

    回答以下問題:

    1.什么是動態代理?

    答:Java動態代理類位于ng.reflect包下,一般主要涉及到以下兩個類:

    一、Interface InvocationHandler:該接口中僅定義了一個方法Object:invoke(Object obj,Method method,J2EEjava語言JDK1.4APIjavalangObject.html">Object[] args)。在實際使用時,第一個參數obj一般是指代理類,method是被代理的方法,如上例中的request(),args為該方法的參數數組。這個抽象方法在代理類中動態實現。

    二、Proxy:該類即為動態代理類,作用類似于上例中的ProxySubject,其中主要包含以下內容:

    Protected Proxy(InvocationHandler h):構造函數,估計用于給內部的h賦值。

    Static Class getProxyClass (ClassLoader loader,Class[] interfaces):獲得一個代理類,其中loader是類裝載器,interfaces是真實類所擁有的全部接口的數組。

    Static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理類的一個實例,返回后的代理類可以當作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法)。

    所謂Dynamic Proxy是這樣一種class:它是在運行時生成的class,在生成它時你必須提供一組interface給它,然后該class就宣稱它實現了這些 interface.你當然可以把該class的實例當作這些interface中的任何一個來用。當然啦,這個Dynamic Proxy其實就是一個Proxy,它不會替你作實質性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。

    2.為什么使用動態代理?

    動態代理可以提供對另一個對象的訪問,同時隱藏實際對象的具體事實,代理對象對客戶隱藏了實際對象。動態代理可以對請求進行其他的一些處理,在不允許直接訪問某些類,

相關文章

無相關信息
更新時間2022-09-16 10:07:22【至頂部↑】
聯系我們 | 郵件: | 客服熱線電話:4008816886(QQ同號) | 

付款方式留言簿投訴中心網站糾錯二維碼手機版

電話:
付款方式   |   給我留言   |   我要糾錯   |   聯系我們




主站蜘蛛池模板: 浙江卫视节目表电视猫| 漆黑意志| 王渝萱的电影| 代高政最新短剧| 白培中| 包公决战潘金莲| 广告设计培训速成班| 周超个人资料简介| 上海东方卫视节目表| 大奉打更人电视剧免费在线观看 | 李采潭全部作品| 哈尔移动的城堡 在线观看| 黄大年主要事迹概括| 屁屁视频| 六字真言颂怙主三宝| 四川经济频道节目表| 二年级100个词语| 欧美日韩欧美日韩| 肖红| 孤战迷城电视剧剧情介绍| 儿子给妈妈过生日,妈妈幸福感言| 性裸体视频| 小狗克罗历险记| 我要逃亡1988国语版免费观看| ab变频器中文说明书| 李洋演员个人简介图片| 天台电影| 家庭理论电影| 男女打扑克视频网站| 蓝家宝电影| 小野寺律| 在线免费污视频| 阮经天新电影| 锦绣南歌免费看| 张国立电影作品大全| 房东电影| 九龙城寨在线观看| 美妙天堂第三季| 雨的印记钢琴谱| 成毅最新电视剧赴山海免费看| 余娅|