java动态代理通过proxy与invocationhandler在运行时增强对象功能,要求目标类实现接口,所有调用经invoke方法拦截处理,支持前置、后置、异常增强且不侵入业务代码。

Java 中的代理模式在运行时增强对象功能,核心是通过动态代理机制——不修改目标类源码,也不提前写死代理类,而是在程序启动或调用发生时,由 JVM 实时生成代理对象,并将方法调用“拦截”到自定义逻辑中处理。
必须基于接口,用 Proxy + InvocationHandler
JDK 原生动态代理要求目标对象实现至少一个接口。它靠两个关键组件协作:
- Proxy.newProxyInstance():传入类加载器、接口数组、InvocationHandler 实例,返回一个实现了指定接口的代理对象;
- InvocationHandler.invoke():所有代理对象的方法调用最终都会进入这个方法,你在这里写前置处理(如日志)、调用真实方法(method.invoke(target, args))、再写后置处理(如统计耗时)。
整个过程完全透明:客户端只看到接口类型,调用方式不变,但实际执行链变成了「代理对象 → invoke() → 目标方法」。
增强逻辑写在 invoke 方法里,可复用可组合
同一个 InvocationHandler 实现类,可以代理任意多个不同接口的对象。比如一个 LogHandler,既可用于 UserService,也可用于 OrderService,无需为每个服务单独写代理类。
- 前置增强:检查参数合法性、记录开始时间、校验权限;
- 后置增强:打印返回值、计算执行耗时、统一格式化响应;
- 异常增强:捕获业务异常并转为统一错误码,避免暴露堆栈。
多个增强点还能按需组合,例如先做权限校验,再记日志,最后测性能——这些都封装在 invoke 内部逻辑中,与业务代码彻底解耦。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
不改原有代码,符合开闭原则
目标类(RealSubject)完全不用感知代理的存在。它只需专注实现接口定义的业务逻辑,比如 UserServiceImpl.addUser() 只管存用户,不关心是否被日志包裹或事务保护。
- 新增增强?改 InvocationHandler 即可,目标类不动;
- 替换增强策略?换一个 Handler 实例,一行 new 代码的事;
- 临时关闭某项增强?在 invoke 中加个开关变量,甚至从配置中心读取开关状态。
这种设计让横切关注点(日志、事务、监控等)真正实现集中管理,也是 Spring AOP 底层依赖的基础机制。
注意局限:接口是硬性前提
JDK 动态代理只能代理接口。如果目标类没实现任何接口,就得换方案:
- 用 CGLIB:通过字节码技术生成目标类的子类,在子类方法中插入逻辑;
- 但 CGLIB 要求目标类不能是 final,方法也不能是 final,否则无法重写;
- 日常开发中,只要合理设计接口(如 Service 层强制接口化),JDK 动态代理就足够稳定高效。
本质上,运行时增强不是魔法,而是把“方法调用”这一动作从直接执行,变成一次可控的委托调度——调度权交给你写的 invoke 方法,功能自然就活起来了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










