我的理解:核心,在不改变原来的代码的情况下,如果要实现拓展新的功能,通过代理实现,再调用代理,横向开发
动态代理我的理解:和静态代理作用是一样的,但是静态代理我们代理的是一个角色,动态代理可以代理一类角色
一个动态代理,一般代理某一类业务,可以代理多个类,代理的是接口
首先必须先了解动态代理的优点:
1、代码复用性拉满、所有类共用,不用重复编码
2、易维护
3、解耦彻底:业务只管业务、日志、权限等通用逻辑全部集中管理
4、适合批量全局增强:全接口加监控、全方法加事务,一行业务代码不用改。
还有一个优点:
静态代理:代码提前写好,编译就有 class 文件; 动态代理:代码一行没写,程序跑起来的时候 JVM 临时在内存现写 class,用完就丢,硬盘不留文件。
从头到尾,你没有新建任何代理类的 Java 文件。 程序跑起来之后(运行阶段),JDK/CGLIB 在内存里临时凭空拼出一份全新的 class 字节码,直接交给 JVM 加载使用。 硬盘全程不会多出任何代理类的.java/.class 文件,程序关闭,内存里这份临时 class 直接消失。这就是运行时自动生成。
静态代理:手写代理类,少量场景能用,多了必难维护;
动态代理:运行自动生成,一套代码通用,适配绝大多数开发。静态代理有的他都有
静态怕多类、怕改方法;动态怕没接口(JDK)、怕 final(CGLIB)。
从零完整复盘,抛弃复杂术语,一层一层捋顺
1. 核心本质:代理是什么?
不管静态、动态代理,套路永远是: 调用方不直接调用真实业务类,先走代理。 代理负责:日志、权限、事务、耗时统计; 真实业务类只做本职功能,杂活全部剥离。
举例子:你要调用用户新增方法 正常:你 → UserServiceImpl(真实类) 代理模式:你 → 代理类 → UserServiceImpl 好处:不改真实类代码,就能在方法前后加额外功能。
2. 静态代理痛点(引出为什么需要动态代理)
静态代理:你手动新建代理.java 文件。 一个真实业务类,必须手写一个专属代理类。 10 个业务类 = 手写 10 个代理类。 如果业务新增方法,所有代理类必须手动新增对应方法,维护极其麻烦。
静态代理的代理类:编译前就写好,编译完硬盘永久存在代理.class 文件。
3. 动态代理最关键:没有手写代理类
你全程只写 3 类代码: 1)业务接口 2)真实实现类 3)拦截处理器(InvocationHandler) 从头到尾,你没有写任何代理的 Java 文件。 硬盘里不存在代理的.java、代理.class。
重点:运行时生成到底发生了什么?
代码执行到Proxy.newProxyInstance这一行(程序跑起来的瞬间):
- JDK 根据接口信息,在内存里拼出来一份全新 class 字节码(代理类);
- JVM 加载这份内存里的 class,创建出代理对象;
- 你调用代理的任意方法,全部跳转进 invoke 方法;
- invoke 写增强逻辑(日志),再调用真实对象的方法;
- 程序停止,内存清空,这份临时代理 class 直接消失,硬盘不留任何痕迹。
简单说:代理类没有提前准备,程序跑起来临时现做,用完扔掉。
4. 完整执行链路(JDK 动态代理标准流程)
调用者 → 运行时生成的代理对象 → invoke 拦截方法(前置增强)→ 真实对象执行业务 → 后置增强返回结果
5. 两个动态代理分类区别(极简)
JDK 动态代理
硬性要求:真实类必须实现接口。 运行生成的代理类实现和目标一模一样的接口。 限制:没有接口完全不能用。
CGLIB 动态代理
不需要接口。 运行时生成目标类的子类,靠重写父类方法实现拦截。 限制:final 类不能被继承,无法代理;final、私有方法拦截不到。
6. 最大优势,一句话记住
只写一份拦截增强代码,所有业务类全部复用。 以后新增业务类、新增方法,不用修改代理相关任何代码。 这是动态代理碾压静态代理的核心。
7. 配套生活化重讲
静态代理:每个快递员单独配专属驿站(手写代理),快递员越多驿站越多。 动态代理:只有 1 个通用驿站(handler),没有专属驿站。程序运行时临时给当前快递员搭一个临时驿站(内存生成代理),用完拆掉。无论多少快递员,共用一套驿站规则。
8. 高频误区逐个澄清
- 误区:动态代理生成 java 源码 错。只会在内存生成二进制 class 字节码,不会产生.java 文件。
- 误区:代理 class 会自动保存在电脑 错。默认只在内存,关闭程序就没。只有配置特殊 JVM 参数,才会把 class 保存到硬盘。
- 误区:invoke 执行目标方法用 proxy 错。必须 method.invoke (真实 target, 参数);填 proxy 会无限循环调用。
9. 极简背诵版
- 动态代理不用手写代理类,运行时内存临时创建代理 class;
- 所有方法被统一拦截,可以无侵入增加日志、事务、权限;
- JDK 靠接口,CGLIB 靠继承;
- 一份增强代码适配所有类,易维护,是 SpringAOP、事务底层原理。