2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3. 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各
种数据访问入口
由于虚拟机规范对这 3 点要求并不具体,所以实际的实现是非常灵活的,关于第
1 点,获取类的二进制字节流(class 字节码)就有很多途径:
� 从 ZIP 包获取,这是 JAR、EAR、WAR 等格式的基础
� 从网络中获取,典型的应用是 Applet
� 运行时计算生成,这种场景使用最多的是动态代理技术,在 java.lang.reflect.Proxy
类 中 , 就 是用了 ProxyGenerator.generateProxyClass 来 为 特 定接口生成形 式 为
*$Proxy 的代理类的二进制字节流
� 由其它文件生成,典型应用是 JSP,即由 JSP 文件生成对应的 Class 类
� 从数据库中获取等等
所以,动态代理就是想办法,根据接口或目标对象,计算出代理类的字节码,然
后再加载到 JVM 中使用。但是如何计算?如何生成?情况也许比想象的复杂得
多,我们需要借助现有的方案。
常见的字节码操作类库
这里有一些介绍:java-source.net/open-source…
� Apache BCEL (Byte Code Engineering Library):是 Java classworking 广泛使用的一种框
架,它可以深入到 JVM 汇编语言进行类操作的细节。
� ObjectWeb ASM:是一个 Java 字节码操作框架。它可以用于直接以二进制形式动态
生成 stub 根类或其他代理类,或者在加载时动态修改类。
� CGLIB(Code Generation Library):是一个功能强大,高性能和高质量的代码生成库,
用于扩展 JAVA 类并在运行时实现接口。
� Javassist:是 Java 的加载时反射系统,它是一个用于在 Java 中编辑字节码的类库;
它使 Java 程序能够在运行时定义新类,并在 JVM 加载之前修改类文件。
� ...
实现动态代理的思考方向
为了让生成的代理类与目标对象(真实主题角色)保持一致性,从现在开始将介
绍以下两种最常见的方式:
1. 通过实现接口的方式 -> JDK 动态代理
2. 通过继承类的方式 -> CGLIB 动态代理
注:使用 ASM 对使用者要求比较高,使用 Javassist 会比较麻烦
JDK 动态代理
评论0