Java动态代理技术方案:JDK、CGLib、Javassist、ASM


一、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()方法。

代理的流程

  1. 获取需代理的类实现的所有接口列表;

  2. 确定要生成的代理类的类名,默认为:com.sun.proxy.$ProxyXXXX;

  3. 根据需要实现的接口信息,在代码中动态创建该Proxy类的字节码;

    JDK动态代理通过一个生成代理类的方法来生成代理类的字节码,该方法为:ProxyGenerator.generateProxyClass(String proxyName,class[] interfaces)

  4. 将对应的字节码转换为对应的class对象;

  5. 创建InvocationHandler实例handler,用来处理Proxy所有方法调用;

  6. 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()方法。

代理的流程

  1. 查找被代理类上的所有非final的public类型的方法定义;
  2. 将这些方法的定义转换成字节码;
  3. 将组成的字节码转换成相应的代理的class对象;
  4. 实现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汇编指令有一定的了解。



参考文章:

Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

JDK 和CGLIB、Javassist、ASM之间的差别

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值