美文网首页
Java--动态代理

Java--动态代理

作者: Qi0907 | 来源:发表于2017-06-07 12:02 被阅读0次

首先先理解一下为什么要使用代理。在日常生活中,代理可以解决业务相关双方直接交流的不便的问题,同时还可以提供比直接交流更多的功能,而在编程领域,代理类一般是做些除原始类核心功能以外的其他功能,比如修改权限等需要专门的代理来实现。代码每个类代表一个主要功能,而不是将所有功能混在一个类中,这样的代码清晰有条理,易于维护,如果要修改权限,不必修改原始类代码,直接修改权限代理类就可以了。这样不需要修改权限的代码可以还用原始类,需要的,就调用代理类,不会影响原来的功能。
代理类提供一个与原始相同的接口,以便可以在任何时候替代原始。代理类通常在客户端调用传递给原始类之前或之后,执行某个操作,而不是单纯地将调用传递给原始类,同时,代理类可以在执行原始类操作时,附加其他的操作,相当于对原始类进行封装。
而动态代理的作用是,只要建立一个动态代理类,就可以为多个原始类进行代理,解决了静态代理的问题(一个原始类对应一个静态代理,有多少原始类就有多少静态代理,造成代码琐碎)。
在java的动态代理机制中,有一个重要的接口 InvocationHandler(Interface)和一个重要的类 Proxy(Class),这两个是实现动态代理所必须用到的。每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用

* @param proxy 所代理的真实对象
     *            the proxy instance on which the method was invoked
     * @param method 所要调用真实对象的某个方法的Method对象
     *            the method invoked on the proxy instance
     * @param args 调用真实对象某个方法时接受的参数
     *            an array of objects containing the parameters passed to the
     *            method, or {@code null} if no arguments are expected.
     *            Primitive types are boxed.
     *
     * @return the result of executing the method. Primitive types are boxed.
     *
     * @throws Throwable
     *             the exception to throw from the invoked method on the proxy.
     *             The exception must match one of the declared exception types
     *             of the invoked method or any unchecked exception type. If not
     *             then an {@code UndeclaredThrowableException} is thrown
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

再来看看Proxy类,它的作用是用来动态创建一个代理对象的类,它提供了许多的方法,但是用的最多的就是 newProxyInstance 这个方法

* @param loader 一个ClassLoader对象,
                            定义了由哪个ClassLoader对象来对生成的代理对象进行加载
     *            the class loader that will define the proxy class
     * @param interfaces 一个Interface对象的数组,
                                表示的是将要给需要代理的对象提供一组什么接口,
                                如果提供了一组接口给它,
                                那么这个代理对象就宣称实现了该接口(多态),
                                这样就能调用这组接口中的方法了
     *            an array of {@code Class} objects, each one identifying an
     *            interface that will be implemented by the returned proxy
     *            object
     * @param invocationHandler 一个InvocationHandler对象,
                                        表示的是当这个动态代理对象在调用方法的时候,
                                        会关联到哪一个InvocationHandler对象上
     *            the invocation handler that handles the dispatched method
     *            invocations
     * @return a new proxy object that delegates to the handler {@code h}
     * @throws IllegalArgumentException
     *                if any of the interface restrictions are violated
     * @throws NullPointerException
     *                if the interfaces or any of its elements are null
     */
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
                                          InvocationHandler invocationHandler)
            throws IllegalArgumentException {

之后看一个demo DynamicProxy20170607来看看动态代理如何使用。
最后结果:


Paste_Image.png

“$ProxyN”是代理类名称,由


Paste_Image.png
打印出的,其中 N 是一个逐一递增的阿拉伯数字,代表 Proxy 类第 N 次生成的动态代理类,但不是每次调用 Proxy 的静态方法创建动态代理类都会使得 N 值增加,因为如果对同一组接口(包括接口排列的顺序相同)试图重复创建动态代理类,它会返回先前已经创建好的代理类的类对象,而不会再尝试去创建一个全新的代理类,这样可以节省不必要的代码重复生成,提高了代理类的创建效率。
通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是InvocationHandler类型,也不是定义的那组接口的类型,而是在运行是动态生成的一个对象。
之后调用
Paste_Image.png

通过代理对象来调用接口中的方法,程序就会跳转到由这个代理对象关联到的 handler 中的invoke方法去执行,而这个 handler 对象又接受了一个 helloImpl类型的参数


Paste_Image.png
表示要代理的就是这个helloImpl真实对象,所以此时就会调用 handler(DynamicProxy) 中的invoke方法去执行,可以看到DynamicProxy中的invoke不仅调用了helloImpl这个真实对象(helloImpl实现了Hello接口),还在前后添加了一些操作,另外通过
Paste_Image.png
可以看到具体调用了什么方法,
结果中before say hello,和after say hello都是添加的操作,从Method:public abstract void DynamicProxy20170607.Hello.helloCat()可以看到,确实是调用的Hello接口helloCat的实现方法。
Paste_Image.png
这也就证明了当通过代理对象来调用方法的时候,起实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的。

相关文章

  • Java--动态代理

    首先先理解一下为什么要使用代理。在日常生活中,代理可以解决业务相关双方直接交流的不便的问题,同时还可以提供比直接交...

  • Java--代理模式、动态代理

    代理模式是很常见的一种设计模式,如AppCompatActivity兼容方案,Java中代理模式分为静态代理和动态...

  • Java--动态代理Method源码分析

    在使用动态代理时,要实现接口 InvocationHandler,当我们通过代理对象调用一个方法的时候,这个方法的...

  • Java--反射机制(二)——动态代理

    一、代理模式 定义:给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过...

  • Java--动态代理Proxy源码分析

    java的动态代理通过Proxy的newProxyInstance方法来创建代理对象 从newProxyInsta...

  • 面试系列~动态代理实现与原理

    动态代理有JDK动态代理, CGLIB动态代理, SpringAOP动态代理 一,JDK动态代理  jdk动态代理...

  • 编程常用的设计模式

    动态代理和静态代理 静态代理 动态代理 静态代理与动态代理的区别 JDK中的动态代理和CGLIB 实现动态代理的方...

  • Spring的AOP原理分析

    一 动态代理 动态代理分为JDK动态代理和CGLIB动态代理 jdk动态代理 被代理类(目标类)和代理类必须实现同...

  • 设计模式之代理模式

    代理分为静态代理和动态代理。 动态代理又包括基于JDK的动态代理、基于CGlib 的动态代理、基于Aspectj实...

  • Java高级主题(五)——动态代理

    代理可以分为静态代理、动态代理,动态代理又可以分为 jvm的动态代理 和 cglib的动态代理。像spring框架...

网友评论

      本文标题:Java--动态代理

      本文链接:https://www.haomeiwen.com/subject/vdbofxtx.html