Java動態代理


  在學習《Java編程思想》的時候看到了動態代理,覺得很有意思,現在來做一下總結。

一、代理模式的定義

  為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

二、優點

  (1).職責清晰真實的角色就是實現實際的業務邏輯,不用關心其他非本職責的事務,通過后期的代理完成一件完成事務,附帶的結果就是編程簡潔清晰。
  (2).代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了的作用和保護了目標對象的作用。
  (3).高擴展性

三、模式結構

  一個是真正的你要訪問的對象(目標類),一個是代理對象,真正對象與代理對象實現同一個接口,先訪問代理類再訪問真正要訪問的對象。

四、UML示意圖

 

  我們來看一個普通代理實現的例子:

 1 //客戶端接口
 2 interface Interface {  3 
 4     void doSomething();  5 
 6     void somethingElse(String arg);  7 }  8 
 9 //客戶端實現類,就是執行業務邏輯的類
10 class RealObject implements Interface { 11 
12  @Override 13     public void doSomething() { 14         // TODO Auto-generated method stub
15         System.out.println("doSomething"); 16  } 17 
18  @Override 19     public void somethingElse(String arg) { 20         // TODO Auto-generated method stub
21         System.out.println("somethingElse" + arg); 22  } 23 
24 } 25 
26 //代理類
27 class SimpleProxy implements Interface { 28 
29     private Interface proxied; 30 
31     public SimpleProxy(Interface proxied) { 32         // TODO Auto-generated constructor stub
33         this.proxied = proxied; 34  } 35 
36  @Override 37     public void doSomething() { 38         // TODO Auto-generated method stub
39         System.out.println("SimpleProxy doSomething"); 40  proxied.doSomething(); 41  } 42 
43  @Override 44     public void somethingElse(String arg) { 45         // TODO Auto-generated method stub
46         System.out.println("SimpleProxy somethingElse "+arg); 47  proxied.somethingElse(arg); 48  } 49 
50 } 51 
52 public  class SimpleProxyDemo{ 53     
54     public static void consumer(Interface iface){ 55  iface.doSomething(); 56         iface.somethingElse("hello world"); 57  } 58     
59     public static void main(String[] args){ 60         consumer(new RealObject()); 61         System.out.println("/*****************************/"); 62         consumer(new SimpleProxy(new RealObject())); 63  } 64 }

 運行結果如下:

1 doSomething 2 somethingElsehello world 3 /*****************************/
4 SimpleProxy doSomething 5 doSomething 6 SimpleProxy somethingElse hello world 7 somethingElsehello world

五、Java動態代理

  Java的動態代理比代理的思想更向前邁進了一步,因為它可以動態地創建代理並動態地處理對所代理方法的調用。在動態代理上所做的所有調用都會被重定向到單一的調用處理器上,它的工作揭示調用的類型並確定相應的對策。 

接下來我們來看一下Java動態代理的例子:

 1  interface Interface {  2 
 3     void doSomething();  4 
 5     void somethingElse(String arg);  6 }  7 
 8 class RealObject implements Interface {  9 
10  @Override 11     public void doSomething() { 12         // TODO Auto-generated method stub
13         System.out.println("doSomething"); 14  } 15 
16  @Override 17     public void somethingElse(String arg) { 18         // TODO Auto-generated method stub
19         System.out.println("somethingElse" + arg); 20  } 21 
22 } 23 
24 //動態代理類
25 class DynamicProxyHandler implements InvocationHandler{ 26 
27     private Object proxied; 28     
29     public DynamicProxyHandler(Object proxied) { 30         // TODO Auto-generated constructor stub
31         this.proxied = proxied; 32  } 33 
34  @Override 35     public Object invoke(Object proxy, Method method, Object[] args) 36             throws Throwable { 37         // TODO Auto-generated method stub
38         System.out.println("****proxy: " + proxy.getClass()+
39                 ", method: "+method+ ", args: "+ args); 40         
41         if(args != null){ 42             for (Object arg : args) { 43                 System.out.println("  "+ arg); 44  } 45  } 46         
47         return method.invoke(proxied, args); 48  } 49 } 50 
51 class SimpleDynamicProxy{ 52     
53     public static void consumer(Interface iface){ 54  iface.doSomething(); 55         iface.somethingElse("hello world"); 56  } 57     
58     public static void main(String[] args){ 59         RealObject real = new RealObject(); 60  consumer(real); 61         
62         System.out.println("/*******************************/"); 63         
64         Interface proxy = (Interface)Proxy.newProxyInstance( 65                 Interface.class.getClassLoader(), 66                 new Class[]{Interface.class}, 67                 new DynamicProxyHandler(real)); 68         
69  consumer(proxy); 70         
71  } 72     
73 }

運行結果如下:

1 doSomething 2 somethingElsehello world 3 /*******************************/
4 ****proxy: class com.sun.proxy.$Proxy0, method: public abstract void Interface.doSomething(), args: null
5 doSomething 6 ****proxy: class com.sun.proxy.$Proxy0, method: public abstract void Interface.somethingElse(java.lang.String), args: [Ljava.lang.Object;@756095fc 7  hello world 8 somethingElsehello world

   通過調用靜態方法Proxy.newProxyInstance()可以創建動態代理。這個方法需要得到一個類加載器(你通常可以從已經被加載的對象中獲取其類加載器,然后傳遞給它),一個你希望該代理實現的接口列表(不是類或者抽象類),以及InvocationHandler接口的一個實現。動態代理可以將所有調用重定向到調用處理器,因此通常會向調用處理器的構造器傳遞一個“實際”對象的引用,從而使得調用處理器執行其中介任務時,可以將請求轉發。

   invoke()方法傳遞進來了代理對象,以防你需要區分請求的來源,但是在許多情況下,你並不關心這一點。然而,在invoke()內部,在代理上調用方法時需要格外小心,因為接口的調用將被重定向為對代理對象的調用。

  通常,你會執行被代理的操作,然后使用Method.invoke()將請求轉發給 被代理對象,並傳入必需的參數。這初看起來可能有些受限,就像你只能執行泛化操作一樣。但是,你可以通過傳遞其他的參數,來過濾某些方法的調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM