代理

作者: renwujie | 来源:发表于2018-10-29 16:05 被阅读0次

代理有什么用?

        利用代理机制可以在运行时创建一个实现了一组给定接口(可以是一个或多个)的新类。这种功能只有在编译时无法确定需要实现哪个接口才有必要使用,如实现某些设计模式(适配器模式和修饰器模式),如面向切面编程(AOP)等。

何时使用代理?

        设想这么一种情况:有一个表示接口的Class对象(有可能包含一个或多个接口),它的确切类型在编译时无法知道。要想构造一个实现这个(组)接口的类,就需要使用newInstance方法或者用反射来找出这个类的构造器。但是,因为无法实例化接口,所以就需要在程序处于运行状态时定义一个新类。

        为了解决这个问题,可以让程序生成代码,将这些代码放置在一个文件中;调用编译器编译;然后再加载结果类文件。很显然,这样的速度会比较慢,而且需要将编译器与程序放在一起。

        代理机制是一种更好的解决方案。代理类可以在运行时创建全新的类。这样的代理类可以实现指定的接口。尤其是代理类具有以下方法:

        1. 指定接口所需要的所有方法。

        2. Object类中的所有方法,如:toString、equals等。

        然而,并不能够在运行时去给这些方法定义新的代码。而是要求提供一个调用处理器。

        调用处理器是实现了InvocationHandler接口的类对象。InvocationHandler接口只有一个方法:

        Object invoke(Object proxy, Method method, Object[] args)

        该方法有三个参数:

        1. 动态代理类的引用。可以使用getClass方法得到代理类的的Class类对象从而取得实例的信息,如方法列表,注解等。

        2. 方法对象的引用,代表被代理类对象调用的方法。从中可以得到有关该方法的信息,如:方法名,参数类型,返回类型等。

        3. 参数对象数组,代表调用方法所需的参数。

        无论何时调用代理对象的方法,调用处理器的invoke方法都会被调用。并向其传递Method对象和原始的调用参数。调用处理器必须给出处理调用的方式(即调用处理器的invoke方法中必须给出处理调用的逻辑)。

如何创建代理对象?

        可以使用Proxy类的newProxyInstance方法来创建代理对象。

        Objectnew ProxyInstance(ClassLoader loader, 

                                                Class[] interfaces, 

                                                InvocationHandler h)

        该方法有三个参数:

        1. 一个类加载器(class loader)。作为Java安全模型的一部分,对于系统和从internet下载的类,可以使用不同的类加载器。这里暂时用null,null可以表示使用默认的   类加载器。

        2. 一个Class对象数组。即每个代理类对象都要实现的接口。

        3. 一个调用处理器。

        此时又产生了一些问题。如何定义一个处理器?能够用生成的代理对象做些什么?当然,这两个问题的答案取决于打算使用代理机制来解决什么问题,即要针对情景和目的来决定。

        使用代理机制可能处于很多原因,例如:

        1. 路由对远程服务的方法调用。

        2. 在程序运行期间,将用户接口事件与动作关联起来。

        3. 跟踪方法的调用

代理类的特性

        代理类是在程序运行的过程中创建的。然而一旦创建,代理类和常规类没有任何不同。

        所有的代理类都扩展与Proxy类。一个代理类只有一个实例域——调用处理器,它定义在超类Proxy中。为了旅行代理对象的职责,所需的任何附加数据都必须存储在调用处理器中。

        所有代理类都覆盖了Object类中的toString、equals和hashCode方法。这些方法和所有的代理方法一样,当调用这些方法时,实质是去调用了调用处理器的invoke方法。Object的其他方法(如:clone、getClass)没有被重新定义。

        没有定义代理类的名字,Oracle虚拟机中的代理类Proxy会生成以字符串$Proxy开头的类名。

        对于特定的类加载器和预设的一组接口来说,只能有一个代理类。也就是说,如果使用同一个类加载器和接口数组调用两次newProxyInstance方法的话,那么你将得到同一个类的两个对象。你也可以用getProxyClass获得这个代理类:

        Class proxyClass = Proxy.getProxyClass (null, interfaces) ;

        代理类一定是public final的。如果代理类实现的所有接口都是public,代理类就不属于任何特定的包;否则,所有非public的接口都必须属于同一个包,而且代理类也必须和这些非public的接口处于同一个包中。

        可以通过调用Proxy类的isProxyClass方法测试一个特定的类对象是否代表一个代理类。

更多实例

        demo1

        demo2

        demo3

相关文章

  • 正向代理和反向代理(通俗易懂)

    正向代理:代理端代理的是客户端。反向代理:代理端代理的是服务端。 常用案例 正向代理:如VPN代理客户端 反向代理...

  • 编程常用的设计模式

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

  • JAVA动态代理的实现方式

    1. 静态代理VS动态代理 代理类可以增强被代理对象的方法。可分为静态代理和动态代理。 1.1 静态代理 静态代理...

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

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

  • Nginx作为代理服务

    一、代理服务代理-代为办理(代理理财、代理收货等等) 1.1正向代理 1.2反向代理 1.3代理区别 1.4配置语...

  • Spring之代理模式

    九、代理模式 目录:静态代理、动态代理AOP的底层机制就是动态代理。代理模式分为静态代理和动态代理。接触aop之前...

  • Spring的AOP原理分析

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

  • 静态代理、动态代理

    代理分为静态代理和动态代理 按照代理创建的时期,可以分为静态代理和动态代理: (1) 静态代理:由程序员或者...

  • Java 代理的实现原理

    一、怎样使用代理 二、代理实现的原理 一、代理分为静态代理和动态代理 静态代理:代理对象获得目标对象的引用 动态代...

  • spring aop

    JDK动态代理和CGLib代理 JDK的代理代理类 被代理接口 被代理实现类 启动类: jdk的动态代理是针对接口...

网友评论

      本文标题:代理

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