如何通过Spring AOP记录Rest Controller抛出的异常?
问题解决方案
配置不生效的常见原因
- 多切点表达式连接符错误:多个execution规则需要用
||(或运算符)连接,不能直接拼接或用逗号分隔 - 异常类型不匹配:切面方法指定了仅捕获
GaException,如果Controller抛出的是其他类型异常,不会触发该方法 - 异常被提前捕获:Controller层如果配置了
@ExceptionHandler全局/局部异常处理器,异常会被提前处理,不会向外抛出到切面层 - 切点路径配置错误或方法修饰符不符合要求:Spring AOP默认仅拦截public方法,需要确认Controller的接口方法为public,且包路径和切点表达式匹配
修正后的代码示例
@Aspect @Component public class ExceptionLoggerAspect { // 切点同时匹配Service层GaService所有方法 + Controller包下所有类的所有public方法 @AfterThrowing(pointcut = "execution(* com.b.m.service.GaService.*(..)) || execution(* com.b.m.controller..*.*(..)) ", throwing = "ex") public void logError(JoinPoint joinPoint, GaException ex) { Signature signature = joinPoint.getSignature(); String methodName = signature.getName(); String stuff = signature.toString(); String arguments = Arrays.toString(joinPoint.getArgs()); LOGGER.error("Exception have been caught in method:\n " + "[" + methodName + "] with arguments " + arguments + " and the full toString: [" + stuff + "] \n the exception is: [" + ex.type.getMessage() + " - " + ex.type.getAdditionalInfo() + "]"); } // 可选:如果需要记录Controller抛出的所有类型异常,可新增以下方法 @AfterThrowing(pointcut = "execution(* com.b.m.controller..*.*(..)) ", throwing = "ex") public void logAllControllerException(JoinPoint joinPoint, Exception ex) { Signature signature = joinPoint.getSignature(); String methodName = signature.getName(); String arguments = Arrays.toString(joinPoint.getArgs()); LOGGER.error("Controller method {} throw exception, params: {}, error info: ", methodName, arguments, ex); } }
额外注意事项
- 将上述代码中
com.b.m.controller替换为你实际的Controller层包路径,表达式中..代表匹配该包及其所有子包 - 确认切面类所在包已经被Spring组件扫描覆盖,Spring Boot项目可通过
@ComponentScan指定扫描范围,或直接将切面类放在启动类同级/子包下 - 如果存在全局异常处理器,可在异常处理器中补充日志记录逻辑,避免异常被捕获后切面无法触发
内容的提问来源于stack exchange,提问作者Abdu Muhammadal
相关产品推荐
相关产品推荐

