大家好,我是锋哥。今天分享关于【JDK动态代理与CGLIB实现的区别?】**面试题。**希望对大家有帮助;
JDK动态代理与CGLIB实现的区别?
JDK 动态代理和 CGLIB 动态代理都是 Java 中用于实现代理模式的技术,二者在实现方式和应用场景上有所不同。
1. JDK 动态代理
-
原理 : JDK 动态代理基于接口,使用 Java 提供的
java.lang.reflect.Proxy
类和InvocationHandler
接口来创建代理对象。代理类需要实现一个或多个接口,并在运行时动态生成该接口的实现。 -
使用场景:
- 接口驱动:只有当目标类实现了接口时,才能使用 JDK 动态代理。
- 适用于面向接口的编程,如 AOP(面向切面编程)中的方法拦截等。
-
实现方式:
Proxy.newProxyInstance
方法接受三个参数:- 类加载器(
ClassLoader
) - 代理类所实现的接口列表(
Class<?>[] interfaces
) InvocationHandler
,用于定义方法调用的实际行为。
- 类加载器(
-
优点:
- 实现简单,基于接口,清晰易用。
- JDK 自带,无需引入外部库。
-
缺点:
- 只能代理实现了接口的类,不能代理没有接口的类。
2. CGLIB 动态代理
-
原理: CGLIB(Code Generation Library)是一个通过继承目标类并重写其方法的方式来创建代理对象的技术。CGLIB 通过字节码技术,在运行时动态生成目标类的子类。它可以代理没有实现接口的类。
-
使用场景:
- 适用于 没有实现接口 的类,或者希望通过继承来进行增强的场景。
-
实现方式:
- CGLIB 动态代理基于继承,通过
Enhancer
类来创建代理对象。Enhancer
设置目标类和方法拦截器后,生成目标类的子类。
- CGLIB 动态代理基于继承,通过
-
优点:
- 可以代理没有实现接口的类。
- 灵活性较高,可以对类的所有方法进行增强。
-
缺点:
- 会生成目标类的子类,因此可能会影响性能。
- 如果目标类是
final
类或者方法是final
的,CGLIB 无法代理。 - 需要引入额外的库,增加了依赖。
3. 区别总结
特性 | JDK 动态代理 | CGLIB 动态代理 |
---|---|---|
代理对象 | 只能代理实现了接口的类 | 可以代理没有接口的类 |
实现方式 | 基于反射,动态生成实现了接口的代理类 | 通过继承目标类,生成目标类的子类 |
性能开销 | 由于是基于反射,性能相对较差 | 生成子类的方式性能相对较好,但依然有开销 |
限制 | 只能代理接口 | 不能代理 final 类或方法 |
常见应用场景 | AOP 等面向接口编程场景 | 适用于不需要接口的类,或当需要增强类的所有方法时 |
4. 何时选择 JDK 动态代理或 CGLIB 动态代理
-
JDK 动态代理:
- 如果目标类实现了接口,首选 JDK 动态代理。
- 对于面向接口编程或 AOP 的场景,非常适用。
-
CGLIB 动态代理:
- 当目标类没有接口时,或者需要增强目标类的所有方法时,可以选择 CGLIB。
- 注意:CGLIB 无法代理
final
类或方法,因此,如果目标类或方法是final
,需要避免使用 CGLIB。
总结来说,JDK 动态代理和 CGLIB 动态代理各有优缺点,选择合适的代理方式,需根据实际的业务需求和目标类的特性来决定。