JDK动态代理与CGLIB实现的区别?

大家好,我是锋哥。今天分享关于【JDK动态代理与CGLIB实现的区别?】**面试题。**希望对大家有帮助;

JDK动态代理与CGLIB实现的区别?

超硬核AI学习资料,现在永久免费了!

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 设置目标类和方法拦截器后,生成目标类的子类。
  • 优点

    • 可以代理没有实现接口的类。
    • 灵活性较高,可以对类的所有方法进行增强。
  • 缺点

    • 会生成目标类的子类,因此可能会影响性能。
    • 如果目标类是 final 类或者方法是 final 的,CGLIB 无法代理。
    • 需要引入额外的库,增加了依赖。

3. 区别总结

特性 JDK 动态代理 CGLIB 动态代理
代理对象 只能代理实现了接口的类 可以代理没有接口的类
实现方式 基于反射,动态生成实现了接口的代理类 通过继承目标类,生成目标类的子类
性能开销 由于是基于反射,性能相对较差 生成子类的方式性能相对较好,但依然有开销
限制 只能代理接口 不能代理 final 类或方法
常见应用场景 AOP 等面向接口编程场景 适用于不需要接口的类,或当需要增强类的所有方法时

4. 何时选择 JDK 动态代理或 CGLIB 动态代理

  • JDK 动态代理

    • 如果目标类实现了接口,首选 JDK 动态代理。
    • 对于面向接口编程或 AOP 的场景,非常适用。
  • CGLIB 动态代理

    • 当目标类没有接口时,或者需要增强目标类的所有方法时,可以选择 CGLIB。
    • 注意:CGLIB 无法代理 final 类或方法,因此,如果目标类或方法是 final,需要避免使用 CGLIB。

总结来说,JDK 动态代理和 CGLIB 动态代理各有优缺点,选择合适的代理方式,需根据实际的业务需求和目标类的特性来决定。