前言
在Java中,动态代理主要分为CGLIB动态代理和JDK动态代理,我们从Hutool的源码也可一窥这两者的使用方式和区别;
CGLIB动态代理
JDK动态代理
使用场景
CglibInterceptor
和JdkInterceptor
都是Hutool提供的代理工具,用于在运行时动态地创建对象的代理,以拦截方法调用。它们的主要区别在于代理机制的实现方式和使用场景:
-
实现方式:
- CglibInterceptor:基于CGLIB库实现,通过字节码技术动态生成目标类的子类,并在子类中重写方法来实现拦截。这种方式可以代理没有实现接口的类。
- JdkInterceptor :基于Java原生的
java.lang.reflect.Proxy
类实现,只能代理实现了接口的类。通过实现InvocationHandler
接口,在invoke
方法中定义拦截逻辑。
-
使用场景:
- CglibInterceptor:适用于需要代理没有实现接口的类的情况。由于CGLIB可以创建目标类的子类,因此可以对类中的所有方法进行拦截,包括私有方法(通过桥接方法)。
- JdkInterceptor:适用于代理实现了接口的类。由于Java原生代理的限制,只能拦截接口中声明的方法。
-
性能:
- CGLIB由于需要进行字节码操作,创建代理对象的开销可能会比JDK原生代理稍大一些。但在方法调用层面,CGLIB可以提供与目标对象相似的性能。
- JDK原生代理在创建代理对象时开销较小,但在方法调用时,由于需要通过反射机制,可能会有一定的性能损失。
-
功能:
- CGLIB提供了一些额外的功能,比如可以处理final方法的拦截(通过FastClass机制)。
- JDK原生代理则依赖于Java反射API提供的功能。
-
兼容性:
- CGLIB可以代理任何类,包括final类和方法,但可能会有一些限制,比如不能代理被标记为final的类。
- JDK原生代理只能代理实现了接口的类,不能代理final类。
选择使用CglibInterceptor
还是JdkInterceptor
,通常取决于具体的使用场景和需求。如果需要代理的类没有实现接口,或者需要拦截类中的所有方法(包括私有方法),则CglibInterceptor
可能是更好的选择。如果代理的类已经实现了接口,并且对性能有较高要求,那么JdkInterceptor
可能更合适。