1 动态代理和静态代理
1.1 静态代理
代理模式最主要的就是有一个公共接口(Subject),一个具体的类(RealSubject),一个代理类(Proxy),代理类持有具体类的实例。当Client调用时接口时,实际是Proxy代为执行具体类的实例方法(request)。
1.2 动态代理
- JDK动态代理:利用接口实现代理
- CGLIB动态代理:利用继承的方式实现代理
2 JDK动态代理类
在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。
调用处理器
这样对目标类中的所有方法的调用都会变为对invoke的调用,可以在invoke方法中添加统一的处理逻辑
创建一个动态代理对象步骤主要有两步:
2.1 创建InvocationHandler调用处理器
每个目标类(被代理类)都有一个与之关联的 InvocationHandler 实现类(调用处理器);如果目标类的方法被调用,那么代理便会转发给 InvocationHandler 实现类(调用处理器)的invoke方法。
在此接口中只有一个 invoker 方法。该方法里有三个参数:
- proxy 代理对象
- method 目标类的方法
- args 目标类方法的参数
2.2 创建代理对象
代理对象由Proxy 类进行创建,代理类继承了Proxy类。
newProxyInstance方法中的三个参数
- loader 代理类的类加载器
- interfaces 代理类要实现的接口(需要被代理的目标类方法)
- h 目标类所关联的调用处理器(InvocationHandler)
2.3 实现示例
代理的接口
代理的目标类
调用处理器实现类
代理类
2.4 原理
Proxy#newProxyInstance
Proxy类的newProxyInstance方法创建了一个动态代理对象。主要的代码逻辑如下:
getProxyClass0方法
上面步骤中最为核心的是 获取代理类的getProxyClass0方法。getProxyClass0的主要逻辑如下:
- 从一个 WeakCache 中去获取代理类,如果缓存中存在代理类则从缓存直接获取;
- 如果不存在,则通过代理类工厂创建代理类。
代理类的字节码生成
代理类的产生就是整个动态代理的关键。其步骤如下:
- 首先通过指定的类加载器去验证目标接口是否可被其加载
- 通过接口所在包等条件决定代理类所在包及代理类的全限定名称,代理类名称是包名+$Proxy+id
- 通过 ProxyGenerator.generateProxyClass() 生成字节码数组,然后调用 native 方法 defineClass0() 将其动态生成的代理类字节码加载到内存中
生产的proxy文件
我们可以通过下面的方法将动态生成的类输出成 class 文件:
使用反编译工具对这个class文件进行反编译, 可以查看代理类的源码:
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/3069.html