如何用@Aspect切入继承Exception的自定义SubscriberNotFoundException类?
问题根源分析
你之前的思路存在核心误区:Aspect切面无法直接切入异常类的方法。因为异常类的方法(比如getCode()、getMessage())并不是业务流程中主动调用的目标方法,只是在异常被捕获后才会被访问的对象方法。无论怎么调整Pointcut语法,都无法匹配到这类调用——切面的作用是拦截业务方法的执行动作,而非异常对象的被动方法调用。
正确实现方案
下面两种方法可以实现你要的异常捕获+文件日志记录需求:
方案1:用@AfterThrowing切面捕获抛出的异常
定义切面,匹配所有可能抛出SubscriberNotFoundException的业务方法,在异常抛出时触发日志记录:
@Aspect @Component public class SubscriberExceptionAspect { // 匹配service和web层的所有方法,可根据实际业务范围调整 @Pointcut("execution(* com.xyz.someapp.service..*.*(..)) || execution(* com.xyz.someapp.web..*.*(..))") public void exceptionThrowPointcut() {} // 捕获指定异常并执行日志逻辑 @AfterThrowing(pointcut = "exceptionThrowPointcut()", throwing = "ex") public void logSubscriberException(SubscriberNotFoundException ex) { // 这里实现文件日志写入逻辑,示例: String logContent = String.format("[%s] 捕获异常:code=%d, msg=%s", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), ex.getCode(), ex.getMessage()); try { Files.write(Paths.get("subscriber_error.log"), (logContent + "\n").getBytes(), StandardOpenOption.APPEND); } catch (IOException e) { e.printStackTrace(); } } }
方案2:全局异常处理器+切面日志(更优雅)
如果是Spring Boot项目,可以用@RestControllerAdvice统一处理异常响应,同时结合切面完成日志记录:
// 全局异常处理器,统一返回规范响应 @RestControllerAdvice public class GlobalExceptionHandler { @Autowired private SubscriberExceptionAspect exceptionAspect; @ExceptionHandler(SubscriberNotFoundException.class) public ResponseEntity<Response> handleSubscriberNotFound(SubscriberNotFoundException ex) { // 调用切面的日志记录逻辑 exceptionAspect.logSubscriberException(ex); return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(new Response(ex.getCode(), ex.getMessage(), null)); } }
补充说明
- 如果你坚持要保留原来的try-catch代码,那切面应该切入包含try-catch的控制器/业务方法,而不是异常类本身
- 异常类本身只需要维护异常信息的属性和getter,不需要被切面切入
内容的提问来源于stack exchange,提问作者fr pblcccnt
相关产品推荐
相关产品推荐

