自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java 動(dòng)態(tài)代理(Proxy)

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

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

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

“寫(xiě)一個(gè) ArrayList 類(lèi)的代理,其內(nèi)部實(shí)現(xiàn)和 ArrayList 中完全相同的功能,并可以計(jì)算每個(gè)方法運(yùn)行的時(shí)間。”這是一份考題上的題目,沒(méi)有答案,來(lái)看下實(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 <p>  
  14.  * -----------------------------------------  
  15.  */ 
  16. public class ProxyApp {  
  17.  
  18.  
  19.     public static void main(String[] args){  
  20.           
  21.         //ArrayList代理,通過(guò)代理計(jì)算每個(gè)方法調(diào)用所需時(shí)間  
  22.         List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(  
  23.             ArrayList.class.getClassLoader(),   /*定義代理類(lèi)的類(lèi)加載器,用于創(chuàng)建代理對(duì)象,不一定必須是ArrayList,也可以是其他的類(lèi)加載器*/ 
  24.             ArrayList.class.getInterfaces(),     /*代理類(lèi)要實(shí)現(xiàn)的接口列表*/ 
  25.             new InvocationHandler() {            /*指派方法調(diào)用的調(diào)用處理程序,這里用了匿名內(nèi)部類(lèi)*/ 
  26.                   
  27.                 private ArrayList<Integer> target = new ArrayList<Integer>(); //目標(biāo)對(duì)象(真正操作的對(duì)象)  
  28.                 /**  
  29.                  * <B>方法描述:</B>  
  30.                  * <p style="margin-left:20px;color:#A52A2A;">  
  31.                  * 在代理實(shí)例上處理方法調(diào)用并返回結(jié)果  
  32.                  * @param proxy     代理對(duì)象(注意不是目標(biāo)對(duì)象)  
  33.                  * @param method  被代理的方法  
  34.                  * @param args         被代理的方法的參數(shù)集  
  35.                  * @return <span style="color: #008080;"> 返回方法調(diào)用結(jié)果 </span>  
  36.                  */ 
  37.                 @Override 
  38.                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  39.                       
  40.                     long beginTime = System.currentTimeMillis();  //開(kāi)始時(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

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

  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 <p>  
  11.  * -----------------------------------------  
  12.  */ 
  13. public class ProxyApp {  
  14.     public static void main(String[] args){          
  15.         //ArrayList代理,通過(guò)代理計(jì)算每個(gè)方法調(diào)用所需時(shí)間  
  16.         List<Integer> arrayListProxy = (List<Integer>)Proxy.newProxyInstance(  
  17.             ArrayList.class.getClassLoader(),     /*定義代理類(lèi)的類(lèi)加載器,用于創(chuàng)建代理對(duì)象,不一定必須是ArrayList,也可以是其他的類(lèi)加載器*/ 
  18.             ArrayList.class.getInterfaces(),       /*代理類(lèi)要實(shí)現(xiàn)的接口列表*/ 
  19.             new MyInvocationHandler(new ArrayList<Integer>())         /*指派方法調(diào)用的調(diào)用處理程序,這里用了匿名內(nèi)部類(lè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.     }  

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

  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 <p>  
  14.  * -----------------------------------------  
  15.  */ 
  16. public class ProxyUtil {  
  17.     public enum ArrayListProxy {  
  18.         PROXY;       
  19.         private Object target;    
  20.         ArrayListProxy(){  
  21.             this.target = new ArrayList<Object>();  
  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.     }  

客戶端調(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 <p>  
  10.  * -----------------------------------------  
  11.  */ 
  12. public class ProxyApp {  
  13.     public static void main(String[] args){  
  14.         List<Integer> 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,如果不想用枚舉,就改用普通類(lèi)來(lái)實(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)類(lèi)多重繼承
  5. Java項(xiàng)目經(jīng)驗(yàn)——程序員成長(zhǎng)的關(guān)鍵
責(zé)任編輯:張偉 來(lái)源: fancydeepin的博客
相關(guān)推薦

2011-04-06 11:41:25

Java動(dòng)態(tài)代理

2017-10-12 14:56:11

2011-03-23 10:40:51

java代理模式

2015-09-22 11:09:47

Java 8動(dòng)態(tài)代理

2023-12-06 08:23:44

代理模式設(shè)計(jì)模式

2021-07-06 06:39:22

Java靜態(tài)代理動(dòng)態(tài)代理

2015-09-28 15:59:00

Java動(dòng)態(tài)代理機(jī)制

2011-11-17 14:32:45

Java靜態(tài)代理動(dòng)態(tài)代理

2023-02-24 07:42:30

Java動(dòng)態(tài)代理

2017-05-11 21:30:01

Android動(dòng)態(tài)代理ServiceHook

2010-12-02 13:36:48

Paros proxy網(wǎng)頁(yè)程序漏洞

2015-09-24 08:54:36

java動(dòng)態(tài)代理

2015-09-24 08:55:14

Java動(dòng)態(tài)代理擴(kuò)展

2010-04-21 09:26:54

Java動(dòng)態(tài)代理

2012-02-08 10:12:19

Java反射

2020-04-27 07:28:00

Java反射動(dòng)態(tài)代理

2020-12-28 07:47:35

動(dòng)態(tài)代理AOP

2022-01-26 00:05:00

AOPRPC遠(yuǎn)程調(diào)用

2009-06-22 15:10:00

java 編程AOP

2012-08-10 13:55:56

Java動(dòng)態(tài)代理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)