在运行时期可以按照Java虚拟机规范对class文件的组织规则生成对应的二进制字节码。当前有很多开源框架可以完成这些功能,如ASM,Javassist。
动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
ASM,Javassist:在代码里生成字节码,并动态地加载成class对象、创建实例。即在运行期系统中,遵循Java编译系统组织.class文件的格式和结构,生成相应的二进制数据,然后再把这个二进制数据加载转换成对应的类,这样,就完成了在代码中,动态创建一个类的能力了。
ASM:
ASM 是一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。
Javassist:直接使用java编码的形式,不需要了解虚拟机指令
JDK动态代理,CGLIB:不用写JVM的汇编指令和类的java编码,通过实现接口和继承的方式创建。
JDK动态代理: 某个类必须有实现的接口,而生成的代理类也只能代理某个类接口定义的方法。如果某个类没有实现接口,那么这个类就不能同JDK产生动态代理了。
CGLIB:通过继承完成而且效率比JDK动态代理高。
jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。。
http://blog.csdn.net/heyutao007/article/details/49738887
java动态代理:
比如现在想为RealSubject这个类创建一个动态代理对象,JDK主要会做以下工作:
1. 获取 RealSubject上的所有接口列表;
2. 确定要生成的代理类的类名,默认为:com.sun.proxy.$ProxyXXXX ;3. 根据需要实现的接口信息,在代码中动态创建 该Proxy类的字节码;
4 . 将对应的字节码转换为对应的class 对象;
5. 创建InvocationHandler 实例handler,用来处理Proxy所有方法调用;
6. Proxy 的class对象 以创建的handler对象为参数,实例化一个proxy对象
1.Interface A
2.Class B impl A
3.MyInvocationHandler impl InvocationHandler{
private Object target;//B
invoke(...){
method.invoke(target, args);
4.Class main(){
A a = new B();
InvocationHandler h = new MyInvocationHandler(a);
A proxy = (A)Proxy.newProxyInstance(a.getClass().getClassLoader(), a.getClass().getInterfaces(), h);