【AOP系列】JDK动态代理源码分析(三)
这里通过JDK的源码来查看一下JDK动态代理的实现。
输出Class文件
我们尝试把JDK动态生成的$Proxy0的class给生成出来。
1 | public class JDKAop { |
$Proxy0
生成的委托类的.class文件反编译后的代码
1 | //代理类都继承 Proxy 类 并且实现代理接口List |
其中
1 | public final class $Proxy0 extends Proxy implements List |
通过这行代码我们可以得到一下信息
1.既然他实现了List接口,那么我们当然可以用List来存放这个$Proxy的对象实例。
2.而且前面还生成了final,所以$Proxy也自然不会有子类了。
3.因为Java是单继承的,虽然不知道为啥要继承Proxy,但是这里既然继承了Proxy,那么$Proxy0就不能同时有其他的父类了。这里也可能是为啥JDK只能生成接口类型的派生类的原因,仅仅是可以能【先暂时放一下,后面自己实现一下JDK的动态代理试试,再详细分析】
$Proxy0的详细生成过程
Proxy.newProxyInstance方法
1 | public static Object newProxyInstance(ClassLoader loader, |
主要的几行代码
1 | //生成代理类 |
进一步看一下getProxyClass0这个方法
1 | return proxyClassCache.get(loader, interfaces); |
点击进入,其中调用了apply(key,parameter);
这里都不是关键的点,
进入ProxyClassFactory类中
1 | private static final class ProxyClassFactory |
其中主要做了一下几件事情
1.一些规则检测,如类加载器是否有效,Class是否为接口,接口数组中的接口是否有重复等
2.拼接代理需要的一些信息,如类名$Proxy+递增数字
3.代理类的byte[]生成
4.加载byte[]到内存,并返回Class
接下来我们看一下byte[]是怎么生成的
ProxyGenerator.generateProxyClass();
(如果点击无法进入,需要添加JDK中的tool.jar,如图所图所示)
进入后主要的两行代码
1 | ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2); |
进入generateClassFile()方法
1 | private byte[] generateClassFile() { |
其中主要做了一下几件事情
1.Object对象中的方法特殊处理
2.循环添加方法,及Method对象
3.循环检测返回值类型
4.静态代码块,初始化代码的生成,
5.class标准文件头的拼接
6.最终把所有的数据转换成byte数组返回
有些方法细节就不再具体分析了。到此,基本上已经把JDK的源代码过了一遍了.
总结
通过阅读JDK的源代码,我们可以知道。JDK实现动态代理类的主要方法如下
1.组合要代理的方法,和自己要插入的代码,按照class文件的格式生成byte[],
2.然后通过ClassLoader,将byte[]加载到内存,并获得Class对象。(其中的class文件的加载涉及到JVM相关知识,内容包括:装载,链接,检查,准备,解析和初始化等,感兴趣读者可自行查找相关内容。)
3.最后通过反射获取到一个代理$Proxy类的构造函数,并创建一个对象返回。
1 | { |