环绕通知是Spring AOP中唯一能决定目标方法是否执行、何时执行、如何执行的通知类型,其参数必须为ProceedingJoinPoint,须显式调用proceed()才执行目标方法。

环绕通知(ProceedingJoinPoint)是 Spring AOP 中唯一能**决定目标方法是否执行、何时执行、如何执行**的通知类型。它通过调用 proceed() 方法来放行目标方法,不调用就不会执行。
核心:必须显式调用 proceed() 才会执行目标方法
环绕通知的参数必须是 ProceedingJoinPoint(不能用普通 JoinPoint)。它的 proceed() 方法相当于“开关”:
- 调用
proceed()→ 目标方法正常执行,通知可获取其返回值或捕获异常 - 不调用
proceed()→ 目标方法被跳过,完全由通知逻辑接管 - 多次调用
proceed()→ 目标方法会执行多次(谨慎使用)
常见控制方式示例
✅ 允许执行并处理结果
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
@Around("execution(* com.example.service.*.*(..))")
public Object logAndProceed(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("前置日志");
Object result = joinPoint.proceed(); // ✅ 放行
System.out.println("后置日志,返回值:" + result);
return result;
}✅ 条件拦截(如权限校验失败时阻止执行)
立即学习“Java免费学习笔记(深入)”;
@Around("@annotation(org.springframework.web.bind.annotation.PostMapping)")
public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable {
if (!hasPermission()) {
throw new AccessDeniedException("无权限");
// ❌ 不调用 proceed(),目标方法不会执行
}
return joinPoint.proceed(); // ✅ 有权限才放行
}✅ 修改入参后执行(需注意参数类型匹配)
@Around("execution(* com.example.service.UserService.updateUser(..))")
public Object modifyParam(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
if (args.length > 0 && args[0] instanceof User) {
User user = (User) args[0];
user.setUpdatedAt(new Date()); // 修改参数
args[0] = user;
}
return joinPoint.proceed(args); // ✅ 传入新参数数组
}注意事项
-
proceed()只能调用一次(除非明确需要重试或重复逻辑) - 若目标方法抛出检查异常,
proceed()声明抛出Throwable,需向上声明或 try-catch 处理 - 不能在
after类通知中调用proceed()—— 环绕通知是唯一支持该操作的通知类型 - 嵌套多个环绕通知时,执行顺序遵循 AOP 链,
proceed()触发下一个通知或目标方法

















