在Java的动态代理机制中,有两个重要的类。一个是InvocationHandler,另一个是Proxy。

  • InvocationHandler:每一个动态代理类都必须要实现InvocationHandler接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。

    /*** * @param proxy     代理的真实对象* @param method    调用真实对象的某个方法的method对象* @param args      调用方法时传的参数* @return          调用结果* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}
  • Proxy:动态的创建一个代理对象的类,我们用的比较多的就是newProxyInstance这个方法。

     /**** @param loader      ClassLoader对象,由哪个ClassLoader对象来对生成的代理对象进行加载* @param interfaces  Interface对象数组,提供一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这个我们就能调用这组接口中的方法了* @param h           InvocationHandler对象,当这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上*/@CallerSensitivepublic static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {}
  • Demo

    Subject接口

    public interface Subject {    void say(String str);
    }

    RealSubject类

    public class RealSubject implements Subject {    @Overridepublic void say(String str) {System.out.println("hello , " + str);}
    }

    动态代理类

    public class DynamicProxy implements InvocationHandler {    // 要代理的真实对象private Object target;    // 给代理的真实对象赋初始值public DynamicProxy(Object target) {        this.target = target;}    @Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();        // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用method.invoke(target, args);after();        return null;}    public void before() {System.out.println("before...");}    public void after() {System.out.println("after...");}
    }

    Client类

    public class Client {    public static void main(String[] args) {Subject realSubject = new RealSubject();        // 将要代理的真实对象传进去,最后是通过该真实对象来调用其方法的InvocationHandler handler = new DynamicProxy(realSubject);        // 通过Proxy来创建对象Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);System.out.println(subject.getClass().getName());subject.say("webb");}
    }

    输出结果

    com.sun.proxy.$Proxy0
    before...
    hello , webbafter...

    我们看到subject.getClass().getName()看到打印出来的是 $Proxy0,首先解释下为什么这里可以将其转换为Subject类型的对象?原因就是在newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么这个代理对象就会实现这种组接口,这个时候我们可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将它转化为Subject类型。同时我们一定要记住,通过Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。

    当我们执行subject.say("webb");的时候,会自动跳转到由这个代理对象关联到的handler中的invoke方法去执行,而handler对象又接受了一个RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用handler中的invoke方法去执行。

转载于:https://blog.51cto.com/12879490/1922310

Java动态代理机制相关推荐

  1. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  2. Java 动态代理机制分析及扩展,第 1 部分

    引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...

  3. Java 动态代理机制分析及扩展

    简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟推演了动态代理类的可能实现,向读者阐述了一个完整的 Java 动态代理运作过程,希望能帮助读者加深对 Java 动 ...

  4. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  5. 详解Java动态代理机制

    之前介绍的反射和注解都是Java中的动态特性,还有即将介绍的动态代理也是Java中的一个动态特性.这些动态特性使得我们的程序很灵活.动态代理是面向AOP编程的基础.通过动态代理,我们可以在运行时动态创 ...

  6. Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

    class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出 ...

  7. JVM插桩之四:Java动态代理机制的对比(JDK和CGLIB,Javassist,ASM)

    一.class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件, ...

  8. Java动态代理机制详解

    class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出 ...

  9. 彻底理解JAVA动态代理

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 代理模式的结构如下图所示. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public ...

最新文章

  1. 测试驱动开发 测试前移_测试驱动的开发可能看起来是工作的两倍-但无论如何您都应该这样做...
  2. (深入理解)model.eval() 、model.train()以及torch.no_grad() 的区别
  3. 一个代理商×××条件
  4. OpenCV reshape函数需要注意的细节
  5. python linux 优化_Python 代码性能优化技巧
  6. TCP/IP数据包结构具体解释
  7. 分针网——每日推荐:PHTML解析原理
  8. 博弈论 —— 公有知识与共同知识
  9. 使用 k8s 搭建 confluence 6.10.x 版本
  10. 在framework和hal添加log
  11. Vue 返回记住滚动条位置详解
  12. 【转】NB-IoT移远BC95使用小结
  13. 关于微信卡券网页跳转链接能力的下线
  14. 计算机音乐红色彼岸花,红色彼岸花 - 刘雨Key - 5SING中国原创音乐基地
  15. HMM隐马尔科夫模型
  16. 怎么批量下载哗哩哗哩B站视频
  17. 服务器厂商对VMware vSphere的驱动支持
  18. 未定义标识符ULONG_PTR,BOOL等错误解决方法 vs2013
  19. ECMAScript 2019(ES10) 的新特性总结
  20. Golang源码探究 —— 网络轮询器netpoller

热门文章

  1. 大厂线上案例复盘--代码漏洞
  2. memcacheq 服务安装与原理
  3. Excel在.Net 环境下Web方式下驻留内存问题的解决
  4. Asp.net 2.0 C#实现压缩/解压功能
  5. 回归——同步更新github.io
  6. Linux下gdb attach的使用(调试已在运行的进程)
  7. 回调函数在C/C++中的使用
  8. 【网络】通讯名词解释:带宽、速率、波特率、奈奎斯特定律、香农定理
  9. 【linux】串口编程(三)——错误处理
  10. c盘扩展卷是灰色的_银行电脑win7-C盘满了怎么办