温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java Proxy 代理和 cglib 区别

发布时间:2026-10-09 16:40:19 来源:亿速云 阅读:84 作者:小樊 栏目:编程语言

在 Java 中,JDK 动态代理(java.lang.reflect.Proxy) 和 CGLIB 代理 都是实现“运行时动态生成代理对象”的技术,常用于 AOP、事务、日志等场景。它们的核心区别如下:


一、根本区别

对比项 JDK Proxy(Java 原生) CGLIB
作者 JDK 自带 第三方(基于 ASM)
代理方式 基于接口 基于继承(子类)
是否依赖接口 ✅ 必须 ❌ 不需要
生成代理原理 实现接口 + 反射调用 继承目标类 + 字节码增强
性能(早期) 较慢 较快
性能(现代 JDK) 接近甚至更好 仍快但差距变小
对 final 支持 接口无 final 问题 ❌ 不能代理 final 类 / final 方法

二、JDK Proxy 特点

✅ 优点

  • JDK 原生,无需额外依赖
  • 使用简单、稳定
  • 安全性好(只代理接口)

❌ 缺点

  • 只能代理接口
  • 目标类必须实现接口

示例

public interface UserService {
    void save();
}

UserService proxy = (UserService) Proxy.newProxyInstance(
    clazz.getClassLoader(),
    new Class[]{UserService.class},
    (p, method, args) -> {
        System.out.println("before");
        Object result = method.invoke(target, args);
        System.out.println("after");
        return result;
    }
);

三、CGLIB 特点

✅ 优点

  • 可以代理普通类(无接口也能用)
  • 性能较好(方法调用直接字节码)
  • 功能更强(可拦截任意方法)

❌ 缺点

  • 需要引入依赖(如 Spring 已内置)
  • 不能代理 final 类 / final 方法
  • 生成子类,构造函数会被调用

示例

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
    System.out.println("before");
    Object result = proxy.invokeSuper(obj, args);
    System.out.println("after");
    return result;
});
UserService proxy = (UserService) enhancer.create();

四、Spring 中的选择规则

Spring AOP 默认策略:

  • 有接口 → 使用 JDK 动态代理
  • 无接口 → 使用 CGLIB
  • 可强制使用 CGLIB:
@EnableAspectJAutoProxy(proxyTargetClass = true)

五、什么时候用哪个?

✅ 用 JDK Proxy:

  • 已有接口
  • 追求标准、稳定
  • 不依赖第三方库

✅ 用 CGLIB:

  • 没有接口
  • 需要代理普通类
  • 对性能要求高(历史场景)

六、一句话总结

JDK Proxy 代理“接口”,CGLIB 代理“类”;
有接口用 JDK,没接口用 CGLIB。

如果你愿意,我也可以从 源码层面 或 性能测试对比 再深入讲。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手