当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

动态代理是如何工作的?

发表于: 2015-04-13   作者:dsxwjhf   来源:转载   浏览次数:
摘要: 我们知道,动态代理主要基于 java.lang.reflect 包下的两个类,一个是 InvocationHandler ,一个是 Proxy 。一个简单的 Dynamic Proxy 的构造过程如下: ================================================== public class MyInvocationHandler implemen
我们知道,动态代理主要基于 java.lang.reflect 包下的两个类,一个是 InvocationHandler ,一个是 Proxy 。一个简单的 Dynamic Proxy 的构造过程如下:

==================================================

public class MyInvocationHandler implements InvocationHandler {

    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // Do something here.
        return method.invoke(target, args);
        // Do something here.
    }
}

public class ProxyGenerator {

    public static Object generateProxy(Object target, InvocationHandler h) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), h);
    }

}

Hello hello = new Hello();
MyInvocationHandler h = new MyInvocationHandler();
h.setTarget(hello);
Object proxy = ProxyGenerator.generateProxy(hello, h);
IHello iHello = (IHello) proxy;
iHello.sayHello();

==================================================

OK ,这段大家都知道,但 invoke() 方法到底是如何作用到 Proxy 上的呢?
我们可以加上 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
这句话,让生成的 Proxy 字节码存储在硬盘上,然后反编译该字节码,看看动态代理的原理。

观察生成的代理类的源码,我们发现它覆写了接口中的所有方法,以及从 java.lang.Object 中继承过来的方法,如: toString() 、 equals() 、 hashCode() 等。以 sayHello() 方法为例,在代理类中它被覆写成了这个样子:
public final void sayHello() {
    // 此处省略虚拟机自动添加的异常处理等
    this.h.invoke(this, m3, null);
    return;
}

这些方法使用这种统一的格式进行方法调用:
this.h.invoke(this, method, args);
下面来解释一下这句话的各个部分。

this.h: InvocationHandler 的实例。我们知道, Proxy.newProxyInstance() 的时候,把一个 InvocationHandler 实例作为它的第三个参数。事实上在最终生成的 Proxy 中,它持有这个 InvocationHandler 实例,所以能通过 this 引用到。

invoke: 没有任何高深的东西,它就是一个 InvocationHandler 的实例 this.h 对它的实例方法 invoke() 的一次普通调用。换句话说,我们在 InvocationHandler 中覆写的方法在这里被回调了,发挥作用了!我们再来复习一下这个方法的定义:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
第一个参数代表 proxy ,在最终生成的 Proxy 实现中就是它自己。
第二个参数代表方法,比如接口中的方法、 toString 、 equals 、 hashCode 等。这些方法将在代理类的静态块中初始化好,比如:
static {
    m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[1] { Class.forName("java.lang.Object") });
    m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
    m3 = Class.forName("com.test.IHello").getMethod("sayHello", new Class[0]);
}
第三个参数不用解释,代表参数。

动态代理是如何工作的?

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
从JDK1.3开始,Java就引入了动态代理的概念。动态代理(Dynamic Proxy)可以帮助你减少代码行数,真
java动态代理就是动态的为委托类生成代理类,相比静态代理需要预先编写代理类源码,动态代理只需要
动态代理 1、动态代理执行过程 代理对象执行一个方法的时候,会调用注入的InvocationHandler的invok
动态代理(Dynamic Proxy) 在了解动态代理之前先来简单的回顾下代理模式 一、代理的概念:生活中的
目录 背景公共代码5种代理模式第一种:ClassProxy第二种:ClassProxyWithTarget第三种:InterfacePr
AOP(面向方面)的思想,就是把项目共同的那部分功能分离开来,比如日志记录,避免在业务逻辑里面夹
概述 代理 生活中的代理:比如暴雪又新出了一款游戏,作为一个中国用户,没有很好的方式直接从美国
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目
代理设计在Java开发中使用较多的一种设计模式,所谓的代理设计就是指由一个代理主题来操作真实主题
代理设计在Java开发中使用较多的一种设计模式,所谓的代理设计就是指由一个代理主题来操作真实主题
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号