Spring Boot AOP (四)与事务、异常处理交互

3 阅读3分钟

Spring Boot [AOP] (四)与事务、异常处理交互

1. 引言

在企业项目中,AOP 不仅用于日志和[性能监控],还与 事务管理异常处理 密切相关。理解 AOP、事务、异常三者的执行顺序 对架构设计和问题排查至关重要。

Spring 事务是通过 AOP 代理实现的,@Transactional 注解会生成一个事务切面,织入目标方法。


2. @Transactional 与 AOP 结合

2.1 核心机制

  1. @Transactional 注解会被 TransactionInterceptor 处理
  2. Spring 使用 环绕通知(Around Advice)在方法调用前开启事务,方法执行后提交或回滚事务
  3. 如果目标方法抛出异常,事务回滚策略生效

2.2 示例代码

@Service
public class UserService {

    @Transactional
    public void createUser(String name) {
        System.out.println("创建用户: " + name);
        if (name.equals("error")) {
            throw new RuntimeException("模拟异常");
        }
    }
}
@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service..*.*(..))")
    public void logBefore(JoinPoint jp) {
        System.out.println("日志前置: " + jp.getSignature());
    }

    @AfterReturning("execution(* com.example.service..*.*(..))")
    public void logAfter(JoinPoint jp) {
        System.out.println("日志后置: " + jp.getSignature());
    }
}

AI写代码java
运行
12345678910111213141516171819202122232425

3. AOP 与事务执行顺序

切面类型执行时机
LoggingAspect@Before方法执行前
TransactionInterceptor@Around方法执行前开启事务
目标方法-执行业务逻辑
TransactionInterceptor@Around方法执行后提交或回滚事务
LoggingAspect@AfterReturning / @AfterThrowing方法返回后执行日志/异常记录

Mermaid 流程图:AOP + 事务 + 异常

正常返回

异常抛出

方法调用

LoggingAspect @Before

TransactionInterceptor @Around 前开启事务

执行目标方法

TransactionInterceptor 提交事务

TransactionInterceptor 回滚事务

LoggingAspect @AfterReturning

LoggingAspect @AfterThrowing

返回客户端


4. 异常通知与事务交互

4.1 异常通知触发条件

  • @AfterThrowing 仅在目标方法抛出异常时执行
  • @AfterReturning 仅在方法正常返回时执行
  • @After 无论成功或异常都会执行

4.2 示例

@Aspect
@Component
public class ExceptionAspect {

    @AfterThrowing(pointcut = "execution(* com.example.service..*.*(..))", throwing = "ex")
    public void logException(JoinPoint jp, Throwable ex) {
        System.out.println("捕获异常: " + ex.getMessage() + " 方法: " + jp.getSignature());
    }
}

AI写代码java
运行
123456789

5. 方法调用顺序示意图

TargetLoggingAspectTransactionInterceptorProxyClientTargetLoggingAspectTransactionInterceptorProxyClient调用 createUser("Tom")@Before开启事务执行目标方法返回/异常提交或回滚事务@AfterReturning / @AfterThrowing返回结果


6. 多切面 + 异常 + 事务组合

@Aspect
@Component
@Order(1)
public class LoggingAspect {
    @Before("execution(* com.example.service..*.*(..))")
    public void before(JoinPoint jp) { System.out.println("日志前置"); }
}

@Aspect
@Component
@Order(2)
public class TransactionAspect {
    @Around("execution(* com.example.service..*.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("事务开始");
        try {
            Object result = pjp.proceed();
            System.out.println("事务提交");
            return result;
        } catch (Throwable ex) {
            System.out.println("事务回滚");
            throw ex;
        }
    }
}

@Aspect
@Component
@Order(3)
public class MetricsAspect {
    @AfterReturning("execution(* com.example.service..*.*(..))")
    public void afterReturning(JoinPoint jp) { System.out.println("性能监控"); }
}

AI写代码java
运行
123456789101112131415161718192021222324252627282930313233

执行顺序示意

正常

异常

方法调用

LoggingAspect @Before

TransactionAspect @Around 前

目标方法执行

TransactionAspect 提交事务

TransactionAspect 回滚事务

MetricsAspect @AfterReturning

异常处理切面执行

返回客户端


7. 小结

  • Spring 事务基于 AOP 环绕通知实现
  • 异常通知和事务回滚紧密关联
  • 多切面情况下,通知顺序由 @Order 或 Ordered 控制
  • Mermaid 图直观展示了 多切面 + 事务 + 异常 的方法调用链