一、JDK动态代理
JDK动态代理主要是针对接口的实现类的动态代理。 它会生成一个被代理接口的实现类,并继承Proxy类。
需要注意的是:被代理的类必须有实现的接口,如果某个类没有实现接口,那么这个类就不能使用JDK动态代理。
相关类
Proxy类:java.lang.reflect.Proxy
/** ====================主要公共静态方法==================== **/
// 指定类是否动态代理类
public static boolean isProxyClass(Class<?> cl)
// 得到指定接口集合的动态代理类
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
// 创建指定接口集合的动态代理类实例对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
// 返回指定代理类实例的调用处理程序。
public static InvocationHandler getInvocationHandler(Object proxy)
/** ====================主要私有静态方法==================== **/
// 检查创建代理类所需的权限。
private static void checkProxyAccess(Class<?> caller, ClassLoader loader, Class<?>... interfaces)
// 生成代理类。 在调用之前必须调用checkProxyAccess方法进行权限检查。
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces)
ProxyGenerator类:sun.miscProxyGenerator
// 主要方法
// 生成代理类的字节码
public static byte[] generateProxyClass(String proxyName,class[] interfaces)
代理的特点
-
代理类继承java.lang.reflect.Proxy类
-
代理类实现被代理类上的所有接口
需要注意:代理类也只能代理某个类实现的接口所定义的方法,如果某个类除了实现接口的方法外,还有另外其它方法,则生成的动态代理类中不会有这个方法了。
-
代理类中的所有方法都是final的
-
所有的方法功能的实现都统一调用了InvocationHandler的invoke()方法。
代理的流程
-
获取需代理的类实现的所有接口列表;
-
确定要生成的代理类的类名,默认为:com.sun.proxy.$ProxyXXXX;
-
根据需要实现的接口信息,在代码中动态创建该Proxy类的字节码;
JDK动态代理通过一个生成代理类的方法来生成代理类的字节码,该方法为:ProxyGenerator.generateProxyClass(String proxyName,class[] interfaces)
-
将对应的字节码转换为对应的class对象;
-
创建InvocationHandler实例handler,用来处理Proxy所有方法调用;
-
Proxy的class对象以创建的handler对象为参数,实例化一个proxy对象。
二、CGLib动态代理
CGLib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。
CGLi动态代理可用于**所有类(包括普通类和接口的是实现类)**的动态代理,它会生成一个被代理类的子类并实现MethodInterceptor接口。
相关类
MethodInterceptor接口:rg.springframework.cglib.proxyMethodInterceptor
public interface MethodInterceptor extends Callback {
// Object var1:指被代理的对象。
// Method var2:要调用的方法
// Object[] var3:方法调用时所需要的参数
// MethodProxy var4:JDK的java.lang.reflect.Method类的代理类,可以实现对源对象方法的调用。
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
MethodProxy类:org.springframework.cglib.proxy.MethodProxy
public class MethodProxy {
private Signature sig1;
private Signature sig2;
private CreateInfo createInfo;
private final Object initLock = new Object();
private volatile FastClassInfo fastClassInfo;
// 创建一个方法代理对象(可以直接使用创建的方法代理对象调用原本的方法)
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2)
// 调用被代理对象的指定方法
public Object invokeSuper(Object obj, Object[] args)
}
代理的特点
- 代理类继承被代理类
- 代理类实现MethodInterceptor接口
- 所有的方法功能的实现都统一调用了MethodInterceptor的invoke()方法。
代理的流程
- 查找被代理类上的所有非final的public类型的方法定义;
- 将这些方法的定义转换成字节码;
- 将组成的字节码转换成相应的代理的class对象;
- 实现MethodInterceptor接口,用来处理对代理类上所有方法的请求(这个接口和JDK动态代理InvocationHandler的功能和角色是一样的)
三、Javassist动态代理
Javassist是一个开源的分析、编辑和创建Java字节码的类库。是一种字节码增强技术。
Javassist加入了开放源代码JBoss应用服务器项目,是Jboss的一个子项目。通过使用Javassist对字节码操作为JBoss实现动态AOP框架。其主要的优点,在于简单,而且快速。
Javassist直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
四、ASM动态代理
ASM 是一个Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM可以直接产生二进制class文件,也可以在类被加载入Java虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。
参考文章: