0
点赞
收藏
分享

微信扫一扫

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


http://zhangjunhd.blog.51cto.com/113473/69996

1.Proxy模式



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



下面示例一个代理模式的实现。



<!--[if !vml]-->


<!--[endif]-->


<<interface>>Subject.java


package        com.zj.proxy;

              

publicinterface        Subject {

           void        operation1();

    

           void        operation2(String arg);

}

现实类RealSubject.java


package        com.zj.proxy;

              

publicclass        RealSubject        implements        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        ProxySubject        implements        Subject {

           private        Subject        proxied       ;       //        被代理对象

              

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

              

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

              

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);      

    }      

}

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


举报

相关推荐

0 条评论