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

时间:2021-08-03 15:18:46
http://zhangjunhd.blog.51cto.com/113473/69996 1.Proxy模式代理模式支持将某些操作从实际的对象中分离出来,通过它的代理类提供处理。这样便于修改和管理这些特定的操作。下面示例一个代理模式的实现。<!--[if !vml]-->如何使用Proxy模式及Java内建的动态代理机制
<!--[endif]-->
<<interface>>Subject.java
package com.zj.proxy; publicinterface Subject {    void operation1();        void operation2(String arg);}
现实类RealSubject.java
package com.zj.proxy; publicclass RealSubjectimplements Subject {     publicvoid operation1() {       System.out.println("Realer do operation1");    }     publicvoid operation2(String arg) {       System.out.println("Realer do operation2 with " + arg);    }}
代理类ProxySubject.java
package com.zj.proxy; publicclass ProxySubjectimplements Subject {    private Subjectproxied;//被代理对象     public ProxySubject(Subject proxied) {       this.proxied = proxied;    }     publicvoid operation1() {       System.out.println("Proxyer do operation1");       proxied.operation1();    }     publicvoid 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; publicclass SimpleProxyDemo {    publicstaticvoid consumer(Subject subject) {       subject.operation1();       subject.operation2("ZJ");    }     publicstaticvoid 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 operation1Realer do operation2 with ZJ===Use Proxy===Proxyer do operation1Realer do operation1Proxyer do operation2 with ZJRealer do operation2 with ZJ2.使用Java的动态代理机制设计一个类用于实现InvocationHandle接口,InvocationHandler 是代理实例的调用处理程序实现的接口。 每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。 <<interface>>InvocationHandle.java
package java.lang.reflect; publicinterface 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; publicclass DynamicProxyHandlerimplements InvocationHandler {    private Objectproxied;     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 Objectproxied;即代理实例,也即上文代理模式中介绍的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; publicclass DynamicProxyDemo {    publicstaticvoid consumer(Subject subject) {       subject.operation1();       subject.operation2("ZJ");    }        publicstaticvoid 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 operation1Realer do operation2 with ZJ===Use Proxy===**** proxy: ****class $Proxy0method: public abstract void com.zj.proxy.Subject.operation1()args: nullRealer do operation1**** proxy: ****class $Proxy0method: public abstract void com.zj.proxy.Subject.operation2(java.lang.String)args: [Ljava.lang.Object;@de6f34  ZJRealer do operation2 with ZJ从结果可以发现,通过代理可以得到当前被调用的方法,及其参数。代理过程可以基于此进行逻辑处理,测试程序只是简单的打印这些相关信息。

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