【Java学习】动态代理有哪些形式?

Java动态代理的两种主要形式

动态代理在Java中有两种主要的实现方式,它们各有特点和使用场景:

1. JDK动态代理 (基于接口)

特点

  • Java标准库自带的功能(java.lang.reflect.Proxy
  • 只能代理接口,不能代理普通类
  • 运行时动态生成代理类
  • 性能较好

使用场景

  • 当你的类已经实现了接口时
  • Spring AOP默认使用这种方式

示例代码

java 复制代码
// 接口
interface UserService {
    void saveUser();
}

// 实现类
class UserServiceImpl implements UserService {
    public void saveUser() {
        System.out.println("保存用户");
    }
}

// 创建代理
UserService proxy = (UserService) Proxy.newProxyInstance(
    UserService.class.getClassLoader(),
    new Class[]{UserService.class},
    (proxyObj, method, args) -> {
        System.out.println("前置处理");
        Object result = method.invoke(new UserServiceImpl(), args);
        System.out.println("后置处理");
        return result;
    }
);

proxy.saveUser();

2. CGLIB动态代理 (基于继承)

特点

  • 需要引入第三方库(cglib)
  • 可以代理普通类,不要求有接口
  • 通过继承目标类并重写方法实现代理
  • 生成速度比JDK代理稍慢,但执行效率高

使用场景

  • 当要代理的类没有实现接口时
  • Spring AOP当目标类没有接口时自动使用CGLIB

示例代码

java 复制代码
// 普通类(没有接口)
class ProductService {
    public void addProduct() {
        System.out.println("添加产品");
    }
}

// 创建代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ProductService.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
    System.out.println("前置处理");
    Object result = proxy.invokeSuper(obj, args);
    System.out.println("后置处理");
    return result;
});

ProductService proxy = (ProductService) enhancer.create();
proxy.addProduct();

两种方式的对比

特性 JDK动态代理 CGLIB动态代理
实现方式 基于接口 基于继承
是否需要接口 必须 不需要
性能 生成快,调用稍慢 生成慢,调用快
限制 只能代理接口方法 不能代理final类/方法
依赖 Java内置 需要第三方库

如何选择?

  1. 如果目标对象有接口,优先用JDK动态代理(Spring默认策略)
  2. 如果目标对象没有接口,只能用CGLIB
  3. 对性能要求极高时,可以考虑CGLIB
  4. 需要代理final方法时,只能用JDK动态代理

现代框架如Spring会根据情况自动选择最合适的代理方式。

相关推荐
yaoxin521123几秒前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python
dFObBIMmai10 分钟前
MySQL主从同步中大事务导致的延迟_如何拆分大事务优化同步
jvm·数据库·python
szccyw013 分钟前
mysql如何限制特定存储过程执行权限_MySQL存储过程安全访问
jvm·数据库·python
小白学大数据19 分钟前
Python 自动化爬取网易云音乐歌手歌词实战教程
爬虫·python·okhttp·自动化
努力努力再努力FFF1 小时前
医生对AI辅助诊断感兴趣,作为临床人员该怎么了解和学习?
人工智能·学习
风之所往_2 小时前
Python 3.0 新特性全面总结
python
2401_882273722 小时前
如何在 CSS 中正确加载本地 JPG 背景图片
jvm·数据库·python
极客先躯2 小时前
高级java每日一道面试题-2025年11月24日-容器与虚拟化题[Dockerj]-runc 的作用是什么?
java·oci 的命令行工具·最小可用·无守护进程·完全标准·创建容器的核心流程·runc 核心职责思维导图
用户60648767188962 小时前
AI 抢不走的技能:用 Claude API 构建自动化工作流实战
java
Lucas_coding2 小时前
【Claude Code Router】 Claude Code 兼容 OpenAI 格式 API, Claude code 接入本地部署模型
人工智能·python