@AfterThrowing能捕获Spring容器管理且走代理的Service层异常,需用execution( com.example.service...*(..))精准切点,配合@Service和@Component生效,仅记录告警不改变流程。

Spring AOP 的异常通知(@AfterThrowing)能捕获业务层方法执行中抛出的异常,但要注意它**只拦截被 Spring 容器管理、且走代理路径的方法调用**——直接 new 对象或内部 self 调用均不会触发。
明确切点范围:精准定位 Service 层
异常通知必须绑定到真正会抛出业务异常的方法上。Service 层是典型目标,需用 execution 表达式精确匹配:
- 推荐写法:
execution(* com.example.service..*.*(..))(双点号匹配子包,覆盖所有 service 类下的所有方法) - 避免宽泛:
execution(* *.*(..))会拦截太多无关方法,影响性能且易误伤 - 确保类被 Spring 管理:Service 类必须加
@Service,且不在 new 实例或静态方法中调用
使用 @AfterThrowing 捕获并处理异常
该通知在目标方法抛出异常后执行,适合记录日志、发告警、存库等“事后”动作:
- 基础用法:声明
throwing = "ex"参数,接收原始异常对象 - 示例代码:
@Aspect @Component public class ServiceExceptionAspect { private static final Logger log = LoggerFactory.getLogger(ServiceExceptionAspect.class); <pre class="brush:php;toolbar:false;">@Pointcut("execution(* com.example.service..*.*(..))") public void serviceMethod() {} @AfterThrowing(pointcut = "serviceMethod()", throwing = "ex") public void logServiceException(JoinPoint joinPoint, Throwable ex) { String methodName = joinPoint.getSignature().toShortString(); Object[] args = joinPoint.getArgs(); log.error("Service method failed: {} with args {}", methodName, Arrays.toString(args), ex); }}
Alibabacloud Sdk Client Initialization For Java下载在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 注意:它不改变方法返回值,也不阻止异常向上抛出;如需统一响应,请搭配
@ControllerAdvice在 Web 层处理
区分场景:@AfterThrowing vs @Around
两者能力不同,选错会导致捕获失效或逻辑混乱:
- @AfterThrowing:轻量、安全。只读取异常,适合审计、监控、告警,不影响原有流程
-
@Around:强大但需谨慎。可捕获异常、修改返回、甚至吞掉异常(
try-catch-proceed),但容易掩盖问题、破坏事务边界 - 业务层异常通常只需记录和告警,
@AfterThrowing更合适;若需自动重试、降级或转换异常类型,再考虑@Around
补充关键细节:让捕获真正生效
常见失效原因往往不是语法问题,而是环境或配置疏漏:
- 确认引入了 AOP 依赖:
spring-boot-starter-aop - 检查切面类是否被扫描到:加
@Component或确保在@SpringBootApplication扫描路径下 - 避免 CGLIB 代理冲突:若 Service 类没有接口,Spring 默认用 CGLIB 代理,需确保类非
final,方法也非final或private - 事务与 AOP 顺序:若方法有
@Transactional,异常通知默认在事务回滚之后执行,日志里能看到“已回滚”状态

















