日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Java動(dòng)態(tài)代理(Proxy)

?動(dòng)態(tài)代理可以提供對(duì)另一個(gè)對(duì)象的訪問,同時(shí)隱藏實(shí)際對(duì)象的具體事實(shí),代理對(duì)象對(duì)客戶隱藏了實(shí)際對(duì)象。動(dòng)態(tài)代理可以對(duì)請(qǐng)求進(jìn)行其他的一些處理,在不允許直接訪問某些類,或需要對(duì)訪問做一些特殊處理等,這時(shí)候可以考慮使用代理。目前 Java 開發(fā)包中提供了對(duì)動(dòng)態(tài)代理的支持,但現(xiàn)在只支持對(duì)接口的實(shí)現(xiàn)。

十年建站經(jīng)驗(yàn), 成都做網(wǎng)站、成都網(wǎng)站制作客戶的見證與正確選擇。成都創(chuàng)新互聯(lián)公司提供完善的營銷型網(wǎng)頁建站明細(xì)報(bào)價(jià)表。后期開發(fā)更加便捷高效,我們致力于追求更美、更快、更規(guī)范。

主要是通過 java.lang.reflect.Proxy 類和 java.lang.reflect.InvocationHandler 接口。 Proxy 類主要用來獲取動(dòng)態(tài)代理對(duì)象,InvocationHandler 接口用來約束調(diào)用者行為。

“寫一個(gè) ArrayList 類的代理,其內(nèi)部實(shí)現(xiàn)和 ArrayList 中完全相同的功能,并可以計(jì)算每個(gè)方法運(yùn)行的時(shí)間。”這是一份考題上的題目,沒有答案,來看下實(shí)現(xiàn):

 
 
 
  1. package example;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.concurrent.TimeUnit;  
  8. /**  
  9.  * -----------------------------------------  
  10.  * @描述  TODO  
  11.  * @作者  fancy  
  12.  * @郵箱  fancydeepin@yeah.net  
  13.  * @日期  2012-8-27 

     

  14.  * -----------------------------------------  
  15.  */ 
  16. public class ProxyApp {  
  17.  
  18.  
  19.     public static void main(String[] args){  
  20.           
  21.         //ArrayList代理,通過代理計(jì)算每個(gè)方法調(diào)用所需時(shí)間  
  22.         List arrayListProxy = (List)Proxy.newProxyInstance(  
  23.             ArrayList.class.getClassLoader(),   /*定義代理類的類加載器,用于創(chuàng)建代理對(duì)象,不一定必須是ArrayList,也可以是其他的類加載器*/ 
  24.             ArrayList.class.getInterfaces(),     /*代理類要實(shí)現(xiàn)的接口列表*/ 
  25.             new InvocationHandler() {            /*指派方法調(diào)用的調(diào)用處理程序,這里用了匿名內(nèi)部類*/ 
  26.                   
  27.                 private ArrayList target = new ArrayList(); //目標(biāo)對(duì)象(真正操作的對(duì)象)  
  28.                 /**  
  29.                  * 方法描述:  
  30.                  *   
  31.                  * 在代理實(shí)例上處理方法調(diào)用并返回結(jié)果  
  32.                  * @param proxy     代理對(duì)象(注意不是目標(biāo)對(duì)象)  
  33.                  * @param method  被代理的方法  
  34.                  * @param args         被代理的方法的參數(shù)集  
  35.                  * @return  返回方法調(diào)用結(jié)果   
  36.                  */ 
  37.                 @Override 
  38.                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  39.                       
  40.                     long beginTime = System.currentTimeMillis();  //開始時(shí)間  
  41.                     TimeUnit.MICROSECONDS.sleep(1);  
  42.                     Object obj = method.invoke(target, args);          //實(shí)際調(diào)用的方法,并接受方法的返回值  
  43.                     long endTime = System.currentTimeMillis();   //結(jié)束時(shí)間  
  44.                     System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  45.                     return obj;   //返回實(shí)際調(diào)用的方法的返回值  
  46.                       
  47.                 }  
  48.                   
  49.             }  
  50.         );  
  51.         arrayListProxy.add(2);  
  52.         arrayListProxy.add(4);  
  53.         System.out.println("--------- 迭代 ---------");  
  54.         for(int i : arrayListProxy){  
  55.             System.out.print(i + "\t");  
  56.         }  
  57.     }  

后臺(tái)打印輸出結(jié)果:

 [add] spend 2 ms
[add] spend 1 ms
--------- 迭代 ---------
[iterator] spend 1 ms
2 4

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

 
 
 
  1. package test;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.util.concurrent.TimeUnit;  
  5. public class MyInvocationHandler implements InvocationHandler{  
  6.     private Object target; //目標(biāo)對(duì)象      
  7.     public MyInvocationHandler(Object target){  
  8.         this.target = target;  
  9.     }  
  10.     @Override 
  11.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {          
  12.         long beginTime = System.currentTimeMillis();  
  13.         TimeUnit.MICROSECONDS.sleep(1);  
  14.         Object obj = method.invoke(target, args);  
  15.         long endTime = System.currentTimeMillis();  
  16.         System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  17.         return obj;      
  18.     }  

客戶端調(diào)用改成:

 
 
 
  1. package example;  
  2. import java.lang.reflect.Proxy;  
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. /**  
  6.  * -----------------------------------------  
  7.  * @描述  TODO  
  8.  * @作者  fancy  
  9.  * @郵箱  fancydeepin@yeah.net  
  10.  * @日期  2012-8-27 

     

  11.  * -----------------------------------------  
  12.  */ 
  13. public class ProxyApp {  
  14.     public static void main(String[] args){          
  15.         //ArrayList代理,通過代理計(jì)算每個(gè)方法調(diào)用所需時(shí)間  
  16.         List arrayListProxy = (List)Proxy.newProxyInstance(  
  17.             ArrayList.class.getClassLoader(),     /*定義代理類的類加載器,用于創(chuàng)建代理對(duì)象,不一定必須是ArrayList,也可以是其他的類加載器*/ 
  18.             ArrayList.class.getInterfaces(),       /*代理類要實(shí)現(xiàn)的接口列表*/ 
  19.             new MyInvocationHandler(new ArrayList())         /*指派方法調(diào)用的調(diào)用處理程序,這里用了匿名內(nèi)部類*/ 
  20.         );  
  21.         arrayListProxy.add(2);  
  22.         arrayListProxy.add(4);  
  23.         System.out.println("--------- 迭代 ---------");  
  24.         for(int i : arrayListProxy){  
  25.             System.out.print(i + "\t");  
  26.         }  
  27.     }  

從上面代碼看來,客戶端知道代理的實(shí)際目標(biāo)對(duì)象,還知道怎么樣去創(chuàng)建這樣一個(gè)代理對(duì)象,如果想把這些信息全部對(duì)客戶端隱藏起來,可以將這些代碼挪到一個(gè)類中,將它們封裝起來:

 
 
 
  1. package example;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.concurrent.TimeUnit;  
  8. /**  
  9.  * -----------------------------------------  
  10.  * @描述  TODO  
  11.  * @作者  fancy  
  12.  * @郵箱  fancydeepin@yeah.net  
  13.  * @日期  2012-8-27 

     

  14.  * -----------------------------------------  
  15.  */ 
  16. public class ProxyUtil {  
  17.     public enum ArrayListProxy {  
  18.         PROXY;       
  19.         private Object target;    
  20.         ArrayListProxy(){  
  21.             this.target = new ArrayList();  
  22.         }  
  23.         public List getInstance(){  
  24.               
  25.             return (List)Proxy.newProxyInstance(ArrayList.class.getClassLoader(), ArrayList.class.getInterfaces(),  
  26.                     new InvocationHandler() {     
  27.                         @Override 
  28.                         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  29.                               
  30.                             long beginTime = System.currentTimeMillis();  
  31.                             TimeUnit.MICROSECONDS.sleep(1);  
  32.                             Object obj = method.invoke(target, args);  
  33.                             long endTime = System.currentTimeMillis();  
  34.                             System.out.println("[" + method.getName() + "] spend " + (endTime - beginTime) + " ms");  
  35.                             return obj;   
  36.                         }  
  37.                     });  
  38.         }  
  39.     }  
  40. 客戶端調(diào)用改成:

     
     
     
    1. package example;  
    2. import java.util.List;  
    3. import example.ProxyUtil.ArrayListProxy;  
    4. /**  
    5.  * -----------------------------------------  
    6.  * @描述  TODO  
    7.  * @作者  fancy  
    8.  * @郵箱  fancydeepin@yeah.net  
    9.  * @日期  2012-8-27 

       

    10.  * -----------------------------------------  
    11.  */ 
    12. public class ProxyApp {  
    13.     public static void main(String[] args){  
    14.         List arrayListProxy = ArrayListProxy.PROXY.getInstance();  
    15.         arrayListProxy.add(2);  
    16.         arrayListProxy.add(4);  
    17.         System.out.println("--------- 迭代 ---------");  
    18.         for(int i : arrayListProxy){  
    19.             System.out.print(i + "\t");  
    20.         }  
    21.     }  

    上面代碼中用到了枚舉 enum,如果不想用枚舉,就改用普通類來實(shí)現(xiàn)就行了。

    原文鏈接:http://www.blogjava.net/fancydeepin/archive/2012/08/27/java_proxy.html

    【編輯推薦】

    1. 近期面試經(jīng)歷總結(jié)及公司評(píng)價(jià)(上)
    2. 函數(shù)式編程是一個(gè)倒退
    3. 為什么Java程序占用的內(nèi)存比實(shí)際分配的多
    4. Java 8 Lambda:模擬Mixin實(shí)現(xiàn)類多重繼承
    5. Java項(xiàng)目經(jīng)驗(yàn)——程序員成長的關(guān)鍵

    分享名稱:Java動(dòng)態(tài)代理(Proxy)
    瀏覽地址:http://www.dlmjj.cn/article/dpsjdgs.html