程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 如何使用Proxy模式及Java內建的動態代理機制

如何使用Proxy模式及Java內建的動態代理機制

編輯:關於JAVA

1.Proxy模式

代理模式支持將某些操作從實際的對象中分離出來,通過它的代理類提供處理。這樣便於修改和管理這些特定的操作。

下面示例一個代理模式的實現。

<<interface>>Subject.java
package com.zj.proxy;
public interface Subject {
   void operation1();
   void operation2(String arg);
}

現實類RealSubject.java

package com.zj.proxy;
public class RealSubject implements Subject {
   public void operation1() {
    System.out.println("Realer do operation1");
   }
   public void operation2(String arg) {
    System.out.println("Realer do operation2 with " + arg);
   }
}

代理類ProxySubject.java

package com.zj.proxy;
public class ProxySubject implements Subject {
   private Subject proxied;// 被代理對象
   public ProxySubject(Subject proxied) {
    this.proxied = proxied;
   }
   public void operation1() {
    System.out.println("Proxyer do operation1");
    proxied.operation1();
   }
   public void operation2(String arg) {
    System.out.println("Proxyer do operation2 with " + arg);
    proxied.operation2(arg);
   }
}

測試類SimpleProxyDemo.java

package com.zj.proxy.client;
import com.zj.proxy.Subject;
import com.zj.proxy.RealSubject;
import com.zj.proxy.ProxySubject;
public class SimpleProxyDemo {
   public static void consumer(Subject subject) {
    subject.operation1();
    subject.operation2("ZJ");
   }
   public static void main(String[] args) {
    RealSubject real = new RealSubject();
    System.out.println("===Without Proxy===");
    consumer(real);
    System.out.println("===Use Proxy===");
    consumer(new ProxySubject(real));
   }
}

結果:

===Without Proxy===
Realer do operation1
Realer do operation2 with ZJ
===Use Proxy===
Proxyer do operation1
Realer do operation1
Proxyer do operation2 with ZJ
Realer do operation2 with ZJ

2.使用Java的動態代理機制

設計一個類用於實現InvocationHandle接口,InvocationHandler 是代理實例的調用處理程序實現的接口。

每個代理實例都具有一個關聯的調用處理程序。對代理實例調用方法時,將對方法調用進行編碼並將其指派到它的調用處理程序的 invoke 方法。

<<interface>>InvocationHandle.java

package java.lang.reflect;
public interface InvocationHandler {
   public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable;
}

對應invoke參數:

[1]proxy - 在其上調用方法的代理實例;

[2]method - 對應於在代理實例上調用的接口方法的 Method 實例;

[3]args - 包含傳入代理實例上方法調用的參數值的對象數組,如果接口方法不使用參數,則為 null。

現在設計一個類實現該接口,並提供代理實例。

DynamicProxyHandler.java

package com.zj.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxyHandler implements InvocationHandler {
   private Object proxied;
   public DynamicProxyHandler(Object proxied) {
    this.proxied = proxied;
   }
   public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
    System.out.println("**** proxy: ****\n" + proxy.getClass()
        + "\nmethod: " + method + "\nargs: " + args);
    if (args != null)
      for (Object arg : args)
        System.out.println(" " + arg);
    return method.invoke(proxied, args);
   }
}

這裡的private Object proxied;即代理實例,也即上文代理模式中介紹的RealSubject對象。

在invoke()方法中,我們會打印它的所有參數,並調用當前代理的方法。

測試類DynamicProxyDemo.java

package com.zj.proxy.client;
import java.lang.reflect.Proxy;
import com.zj.proxy.Subject;
import com.zj.proxy.RealSubject;
import com.zj.proxy.dynamic.DynamicProxyHandler;
public class DynamicProxyDemo {
   public static void consumer(Subject subject) {
    subject.operation1();
    subject.operation2("ZJ");
   }
   public static void main(String[] args) {
     RealSubject real = new RealSubject();
    System.out.println("===Without Proxy===");
    consumer(real);
    System.out.println("===Use Proxy===");
    Subject proxy = (Subject) Proxy.newProxyInstance(Subject.class
        .getClassLoader(), new Class[] { Subject.class },
        new DynamicProxyHandler(real));
    consumer(proxy);
   }
}

這裡通過Proxy的靜態方法newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)生成代理類,並傳遞與其關聯的調用處理程序new DynamicProxyHandler(real)。

對於newProxyInstance()的參數:

[1]loader - 定義代理類的類加載器 ;

[2]interfaces - 代理類要實現的接口列表 ;

[3]h - 指派方法調用的調用處理程序 。

測試結果:

===Without Proxy===
Realer do operation1
Realer do operation2 with ZJ
===Use Proxy===
**** proxy: ****
class $Proxy0
method: public abstract void com.zj.proxy.Subject.operation1()
args: null
Realer do operation1
**** proxy: ****
class $Proxy0
method: public abstract void com.zj.proxy.Subject.operation2(java.lang.String)
args: [Ljava.lang.Object;@de
6f
34
  ZJ
Realer do operation2 with ZJ

從結果可以發現,通過代理可以得到當前被調用的方法,及其參數。代理過程可以基於此進行邏輯處理,測試程序只是簡單的打印這些相關信息。

本文出自 “子 孑” 博客,請務必保留此出處http://zhangjunhd.blog.51cto.com/113473/69996

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved