AOP方式解决seata失效问题

seata使用回顾

  1. 在feign接口调用方使用@GlobalTransactional
  2. 在被调用方使用@Transactional
  3. 当调用方出现异常,整体会进行事务的回滚
  4. 当被调用方出现了异常会出现两种情况
    1. 如果系统进行了全局异常捕获,被调用方会进行事务回滚,调用方不会
    2. 如果系统没有进行全局异常捕获或者没有捕获调用方出现的异常,双方都会出现事务的回滚

使用AOP方式解决事务失效问题

​ 一般情况下,我们的系统为了能给前端更好的响应,而不是把一串很长的错误信息给到前端,都会进行全局异常的捕获,所以就会出现seata分布式事务失效的问题

​ 针对此种问题,我们可以使用AOP切面的方式进行解决

编写AOP切面类

package com.ajie.api.aspect;

import com.ajie.common.utils.StringUtils;
import io.seata.core.context.RootContext;
import io.seata.core.exception.TransactionException;
import io.seata.spring.annotation.GlobalTransactional;
import io.seata.tm.api.GlobalTransaction;
import io.seata.tm.api.GlobalTransactionContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Description:
 * @Author: ajie
 */
@Component
@Aspect
@Slf4j
public class SeataTransactionAspect {

    @Before("execution(* com.ajie.*.service.impl..*.*(..))")
    public void beginTransaction(JoinPoint joinPoint) throws TransactionException {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 获取到方法上的注解
        GlobalTransactional globalTransactional = methodSignature.getClass()
                .getAnnotation(GlobalTransactional.class);
        Transactional transactional = methodSignature.getClass().getAnnotation(Transactional.class);
        if (globalTransactional != null || transactional != null) {
            // 如果方法上有事务注解,就手动开启分布式事务
            log.warn("手动开启全局事务");
            GlobalTransaction gt = GlobalTransactionContext.getCurrentOrCreate();
            gt.begin();
        }
    }

    @AfterThrowing(
            throwing = "throwable",
            pointcut = "execution(* com.ajie.*.service.impl..*.*(..))"
    )
    public void rollback(Throwable throwable) throws TransactionException {
        log.warn("捕获到的异常信息,则回滚,异常信息为:{}", throwable.getMessage());
        // 从当前线程获得xid
        String xid = RootContext.getXID();
        if (StringUtils.isNotBlank(xid)) {
            GlobalTransactionContext.reload(xid).rollback();
        }
    }

    @AfterReturning(
            returning = "result",
            pointcut = "execution(* com.ajie.*.service.impl..*.*(..))"
    )
    public void commit(JoinPoint joinPoint, Object result) throws TransactionException {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 获取到方法上的注解
        GlobalTransactional globalTransactional = methodSignature.getClass()
                .getAnnotation(GlobalTransactional.class);
        Transactional transactional = methodSignature.getClass().getAnnotation(Transactional.class);
        if (globalTransactional != null || transactional != null) {
            // 如果方法上有事务注解,就手动提交全局事务
            log.warn("手动提交全局事务");
            // 从当前线程获得xid
            String xid = RootContext.getXID();
            if (StringUtils.isNotBlank(xid)) {
                GlobalTransactionContext.reload(xid).commit();
            }
        }
    }
}
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值