首页 > 编程语言 >如何使用Proxy模式及Java内建的动态代理机制

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

时间:2023-07-28 17:35:19浏览次数:38  
标签:do operation1 Java zj proxy 内建 Proxy com Subject


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


标签:do,operation1,Java,zj,proxy,内建,Proxy,com,Subject
From: https://blog.51cto.com/u_16174476/6885654

相关文章

  • Java 比较两个日期的方法
    三种方法分别是:1)byUsingclassicCompareTomethodofDateclass.2)byusingequals(),before()andaftermethodofDateclass.3)byusingequals(),before()andaftermethodofCalendarclassinJava.标签:<无>代码片段(2)......
  • Java 获取对象的属性及属性值
    获取属性名称:/***获取属性名数组**@paramo对象*@return属性名称*/privateString[]getFiledName(Objecto){Field[]fields=o.getClass().getSuperclass().getDeclaredFields();String[]fieldNames=newString[fields.length];for(inti=0;i<......
  • java——虚拟机、线程
    java虚拟机:是一台想象中的机器,有自己想象的硬件(处理器、堆栈、寄存器等)以及相应的指令系统。生命周期:当执行java程序时,虚拟机开始运行,程序结束虚拟机停止。同一台计算机每多运行一个程序,就会多运行一个虚拟机。虚拟机开始于main()方法。java虚拟机的体系结构:......
  • java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet
    环境信息:JDK17、Tomcat10问题原因我这里编译,打包都是好的,但是一运行发现就报错。错误的原因是Tomcat10里也自带了一些lib包,可以打开Tomcat下lib文件夹,这又涉及到了包的加载顺序了一打开发现Tomcat里的是 JakartaEE,我Maven里引用的还是JavaEE导致的。JavaEE的servlet......
  • 学习Java的第8天
    数据拓展publicclassDemo03{publicstaticvoidmain(String[]args){//*整数拓展进制二进制0b**十进制八进制**0**十六进制**0x**inti=10;inti2=010;//**八进制0**inti3=0x10;//**十六进制0x0~9A~F16**System.out.println(i);System.out......
  • Java学习1
    java学习01简单写写学习期间不知道or感兴趣的一些东西计算机相关前置知识计算机结构系统软件DOS(DiskOperatingSystem)WindowsLinuxUnix,Mac,Android,IOS...windows快捷键关闭窗口 ALT+F4永久删除文件Shift+Delete快捷指令win+R打开我的电......
  • TestNG 使 Java 单元测试轻而易举
    http://www.ibm.com/developerworks/cn/java/j-testng/在每个现代软件包的构造阶段,测试这一实践都扮演着中心角色。过去那种先编写代码,然后有空的时候再测试(或者根本不测试)的日子已经一去不返,因为大多数开发人员现在认识到需要采用编码和测试彼此交织、同步推进的软件方法论,以便尽......
  • java多线程学习-java.util.concurrent详解
    java多线程学习-java.util.concurrent详解(一)Latch/Barrier   Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent,提供了大量高级工具,可以帮助开发者编写高效、易维护、结构清晰的Java多线程程序。从这篇blog起,我将跟大家一起共同学习这些新的Java多线......
  • Java a=a+b和a+=b的区别
    1、对于同样类型的a,b来说两个式子执行的结果确实没有什么区别。但是从编译的角度看吧(武让说的),a+=b;执行的时候效率高。2、对于不同类型的a,b来说2.1不同类型的两个变量在进行运算的时候,我们经常说到的是类型的转换问题。这里,记住两点:一、运算过程中,低精度的类型向高精度类型转......
  • Java面试题 P11:ArrayList和LinkedList区别
    ArrayList:基于动态数组,连续内存存储,适合下标访问(随机访问),扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(往后复制一份,插入新元素),使用尾插法并指定初始容量可以极大提升性能,甚至超过linkedListLin......