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;@de6f34

  ZJ

Realer do operation2 with ZJ
从结果可以发现,通过代理可以得到当前被调用的方法,及其参数。代理过程可以基于此进行逻辑处理,测试程序只是简单的打印这些相关信息。