如何使用Proxy模式及Java内建的动态代理机制

1.Proxy 模式
代理模式支持将某些操作从实际的对象中分离出来,通过它的代理类提供处理。这样便于修改和管理这些特定的操作。
下面示例一个代理模式的实现。

如何使用Proxy模式及Java内建的动态代理机制
 
<<interface>>Subject.java
package com.zj.proxy;
 
public interface Subject {
    void operation1();
   
    void operation2(String arg);
}
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 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);
    }
}
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;@de6f34
  ZJ
Realer do operation2 with ZJ
从结果可以发现,通过代理可以得到当前被调用的方法,及其参数。代理过程可以基于此进行逻辑处理,测试程序只是简单的打印这些相关信息。

本文出处:http://zhangjunhd.blog.51cto.com/113473/69996

你可能感兴趣的:(java,设计模式,Blog)