Java动态代理本质是运行时方法调用拦截,通过代理对象增强行为而非修改类结构:JDK代理基于接口,CGLIB基于子类,均在invoke或intercept中插入日志、权限、事务等逻辑。

Java 中动态代理不是直接增强“类”,而是增强“对象的行为”——它在运行时生成一个新对象(代理对象),该对象实现了与目标对象相同的接口(JDK方式)或继承了目标类(CGLIB方式),并在方法调用时插入自定义逻辑。真正的增强发生在调用层面,而非修改类字节码或类结构本身。
JDK 动态代理:基于接口的运行时增强
JDK 动态代理要求目标对象必须实现至少一个接口,代理对象也只实现这些接口,不改变原类定义。
- 定义目标接口和实现类(如 UserService 和 UserServiceImpl)
- 编写 InvocationHandler 实现类,在 invoke() 方法中写前置/后置逻辑(如日志、权限校验)
- 调用 Proxy.newProxyInstance(),传入类加载器、接口数组、处理器实例,得到代理对象
- 后续对该代理对象的方法调用,都会进入 invoke(),再由你决定是否、何时、如何调用真实对象的方法
CGLIB 动态代理:基于子类的运行时增强
当目标类没有接口,或需要代理具体类的方法时,CGLIB 通过字节码技术生成目标类的子类,并重写非 final 方法,从而实现代理。
- 引入 CGLIB 依赖(如 cglib-nodep)
- 使用 Enhancer 设置父类(即目标类)、回调(MethodInterceptor)
- 在 intercept() 方法中控制方法执行流程,可选择跳过、包装、替换原逻辑
- 生成的代理对象是目标类的子类实例,能代理 public/protected 方法,但不能代理 final 类或 final 方法
增强的关键不在“改类”,而在“截方法”
动态代理的本质是方法调用拦截,不是类增强。它不修改原始类的 .class 文件,也不影响其他实例或后续 new 出的对象。
立即学习“Java免费学习笔记(深入)”;
- 代理对象是独立新实例,其行为由 InvocationHandler 或 MethodInterceptor 定义
- 同一个目标对象可以被多个不同逻辑的代理包装(比如一个加日志、一个加事务、一个做监控)
- 增强逻辑完全解耦:目标类无需知道代理存在,也不依赖任何代理相关代码
- 所有增强都在运行时生效,启动后可按需开关(例如通过配置控制是否启用缓存代理)
实际增强常做的几件事
这些操作都发生在 invoke() 或 intercept() 内部,不侵入业务代码:
- 记录日志:打印方法名、参数、耗时、返回值或异常
- 权限校验:检查当前用户是否有调用该方法的权限,无则抛出异常
- 事务管理:方法开始前开启事务,成功后提交,异常时回滚
- 缓存处理:根据参数查缓存,命中则直接返回,未命中则调用原方法并缓存结果
- 性能监控:用 System.nanoTime() 统计方法执行时间,上报指标


















