AOP 概念:切点/通知/织入与通知顺序
结论先行:AOP(面向切面编程)把日志、事务、权限、监控这类"横切关注点"从业务代码中抽出来独立成切面。五个核心概念:切面(Aspect)、连接点(JoinPoint)、切点(Pointcut)、通知(Advice)、织入(Weaving)。一句话定位:切点决定"切哪里",通知决定"做什么",织入决定"什么时候生效"(Spring 采用运行期动态代理织入)。多个切面的执行顺序由 @Order 决定,@Order 数值小者先执行、包裹在外层。
一、概念速查
| 术语 | 含义 | 类比/要点 |
|---|---|---|
| Aspect 切面 | 切点 + 通知的封装(@Aspect 类) | 一个模块化的横切逻辑 |
| JoinPoint 连接点 | 被拦截的可执行位置 | Spring AOP 中仅指"方法执行" |
| Pointcut 切点 | 匹配连接点的表达式 | execution()/within/@annotation(...) 等 |
| Advice 通知 | 切点处要执行的动作 | 五种:@Before/@After/@AfterReturning/@AfterThrowing/@Around |
| Weaving 织入 | 把通知应用到目标生成代理的过程 | Spring = 运行期动态代理织入 |
二、代码示例
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* com.demo.service.*.*(..))") // 切点:service 包下所有方法
public void serviceLayer() { }
@Around("serviceLayer()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
return pjp.proceed(); // 放行目标方法
} finally {
System.out.println(pjp.getSignature() + " cost " + (System.currentTimeMillis() - start) + "ms");
}
}
}
三、通知执行顺序(Spring 5.2.7+)
- 正常返回:@Around 前段 → @Before → 目标方法 → @AfterReturning → @After → @Around 后段;
- 抛异常:@Around 前段 → @Before → 目标方法抛异常 → @AfterThrowing → @After → @Around 后段(finally 部分仍执行);
- 多切面嵌套:@Order(1) 在最外层,@Order 越大越内层;@Around 不调用 proceed() 则目标方法不执行。
常见追问 / 记忆点
- 追问 1:五种通知怎么选?答:读操作善用 @Before/@AfterReturning;需要吞异常、控制返回值或统计耗时用 @Around(最灵活、可决定是否放行)。
- 追问 2:execution 表达式写法?答:execution(修饰符 返回类型 类路径.方法(参数) 异常),如 execution(* com.demo.service..(..))。
- 追问 3:为什么通知顺序重要?答:事务/缓存/安全等切面叠加时顺序错了会先提交后收尾,导致逻辑错乱;用 @Order 显式控制。
- 记忆点:"切点定位置、通知定动作、织入定时机、@Order 定先后"。