代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

  通过代理层这一中间层,有效的控制对于真实委托类对象的直接访问,同时可以实现自定义的控制策略(Spring的AOP机制),设计上获得更大的灵活性。

  java动态代理的类和接口(jdk1.6源码),g.reflect.Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对象和代理类。

  // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象

  // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例

  2,ocationHandler:调用处理器接口,自定义invokle方法,用于实现对于真正委托类的代理访问。

  3,java.lang.ClassLoader:类装载器类,将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy类与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。

  每次生成动态代理类对象时都需要指定一个类装载器对象:newProxyInstance()方法第一个参数

  // 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用

  // 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象

  3,通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

  4,通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

  为了简化对象创建过程,Proxy类中的newProxyInstance方法封装了2~4,只需两步即可完成代理对象的创建。

  Proxy 类是它的父类,这个规则适用于所有由 Proxy 创建的动态代理类。(也算是java动态代理的一处缺陷,java不支持多继承,所以无法实现对class的动态代理,只能对于Interface的代理)而且该类还实现了其所代理的一组接口,这就是为什么它能够被安全地类型转换到其所代理的某接口的根本原因。

  5,代理类的根类g.Object 中有三个方法也同样会被分派到调用处理器的 invoke 方法执行,它们是 hashCode,equals 和 toString,

  其中,bind方法中的newProxyInstanc方法,就是生成一个代理对象,第一个参数是类加载器,第二个参数是真实委托对象所实现的的接口(代理对象挂在那个接口下),第三个参数this代表当前HelloServiceProxy类,换句话说是使用HelloServiceProxy作为对象的代理。

  invoke方法有三个参数:第一个proxy是代理对象,第二个是当前调用那个方法,第三个是方法的参数。

  源码跟踪Proxy 类// 映射表:用于维护类装载器对象到其对应的代理类缓存

  // 同步表:记录已经被创建的动态代理类类型,主要被方法 isProxyClass 进行相关的判断

  检查接口类对象是否对类装载器可见并且与类装载器所能识别的接口类对象是完全相同的,还会检查确保是 interface 类型而不是 class 类型。

  2,从 loaderToCache 映射表中获取以类装载器对象为关键字所对应的缓存表,如果不存在就创建一个新的缓存表并更新到 loaderToCache。

  loaderToCache存放键值对(接口名字列表,动态生成的代理类的类对象引用)。当代理类正在被创建时它会临时保存(接口名字列表,pendingGenerationMarker)。标记 pendingGenerationMarke 的作用是通知后续的同类请求(接口数组相同且组内接口排列顺序也相同)代理类正在被创建,请保持等待直至创建完成。

  首先根据规则(接口public与否),生成代理类的名称,$ProxyN格式,然后动态生成代理类。

  所有的代码生成的工作都由 ProxyGenerator 所完成了,该类在rt.jar中,需要反编译

  // 如果saveGeneratedFiles的值为true,则会把所生成的代理类的字节码保存到硬盘上

  4,代码生成过程进入结尾部分,根据结果更新缓存表,如果成功则将代理类的类对象引用更新进缓存表,否则清楚缓存表中对应关键值,最后唤醒所有可能的正在等待的线程。

  通过getProxyClass0方法中生成具体的class文件的过程,定义path,讲class文件写到指定的磁盘中,反编译生成的代理class文件。

  发现在静态代码块中获取了的方法有:Object中的equals方法、Object中的hashCode方法、Object中toString方法 ,以及invoke的接口方法。后语至此,JDK是动态生成代理类,并通过调用解析器,执行接口实现的方法的原理已经一目了然。动态代理加上反射,是很多框架的基础。比如Spring的AOP机制,自定义前置后置通知等控制策略,以及mybatis中的运用反射和动态代理来实现插件技术等等。

  如果大家喜欢这篇文章的话,希望大家能够收藏,转发 谢谢!更多相关资讯可以关注西安华美校区,免费获得java零基础教程!额外附送excel教程!返回搜狐,查看更多