761 字
约 2 分钟
26
S27-J04 · AOP 与对象转换:代理、拦截、MapStruct
适用读者:被
setXXX和"切面不生效"折磨的人。
前置:S07-B03(AOP 代理)。
覆盖旧文:381(260) 374(332) + 相关 = 766 点。
扩展点:E-S27-014(MapStruct 与反射拷贝的边界)。
上一篇:S27-J03 · 验证码与风控:滑块设计与实现
下一篇:S27-J05 · 架构演进。
1. 一句话结论
AOP 解决"横切逻辑"(日志/事务/权限),对象转换解决"样板赋值"——两者都在"减少重复代码",但机制完全不同:一个是代理,一个是编译期生成。
| 手段 | 机制 | 运行期开销 |
|---|---|---|
| AOP | 动态代理(S07-B03) | 有(一次间接调用) |
| MapStruct | 编译期生成实现类 | 无(就是普通方法调用) |
| BeanUtils(反射) | 反射拷贝 | 有(明显) |
2. AOP 的边界(复习 + 补充)
| 能切 | 切不到 |
|---|---|
| Spring 管理的 Bean 的 public 方法 | 同类内部自调用(S07-B03) |
| 接口/类代理 | private/final/static |
| 方法级 | 字段访问 |
"为什么 AOP 常被误用":把业务逻辑塞进切面 → 代码更难追踪。判据:这段逻辑"业务"吗? 是 → 不该在切面里。
3. MapStruct:编译期生成(E-S27-014)
@Mapper
interface UserMapper {
UserVO toVO(User user); // 编译期生成实现,字段名自动匹配
}
| 优点 | 注意 |
|---|---|
| 无反射开销 | 字段名不一致要显式 @Mapping |
| 编译期检查 | 嵌套对象要配 @Mapper(uses=...) |
| 可调试(生成源码可见) | 复杂转换逻辑仍要手写 |
判据:"这段转换在热路径上吗?" 在 → MapStruct;一次性/低频 → 反射工具也行,但要接受开销。
4. 三者选型速查
| 场景 | 选 |
|---|---|
| 日志/事务/权限 | AOP |
| 实体 ↔ DTO 转换(多、重复) | MapStruct |
| 字段少、临时用 | 手写或反射 |
| 热路径、高性能 | MapStruct 或手写 |
5. 五个误区
| 误区 | 真相 |
|---|---|
| "AOP 能切所有方法" | 自调用/private 切不到 |
| "切面里写业务更清晰" | 追踪困难 |
| "MapStruct 没开销" | 无反射开销,但仍有方法调用 |
| "反射拷贝够用了" | 热路径上明显慢 |
| "字段名不同也能自动映射" | 需显式 @Mapping |
6. 自检
- 三者机制差异?
- AOP 切不到哪些?
- MapStruct 的收益与注意点?
- 热路径该选什么?
- 为什么"业务逻辑不该在切面里"?
7. 下一篇
S27-J05 · 架构演进:从模块化到 SOA
转换讲完,下一篇讲"什么时候该拆服务"。
本篇属于系列《S27 · 杂项归档与工具实测》。旧文来源:A-381/374 + 相关卡;扩展点 E-S27-014。
S27-J04 · AOP 与对象转换:代理、拦截、MapStruct
https://www.clxhxhhr.top/posts/5622/ 评论
0 条
还没有评论,先写一条吧。