All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.huanminabc.utils_tools.dynamic_datasource.aop.DBTransactionalAspect Maven / Gradle / Ivy

There is a newer version: 1.0.6-RELEASE
Show newest version
package com.gitee.huanminabc.utils_tools.dynamic_datasource.aop;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.gitee.huanminabc.utils_common.base.UniversalException;
import com.gitee.huanminabc.utils_common.spring.SpringContextHolder;
import com.gitee.huanminabc.utils_tools.dynamic_datasource.base.DynamicDataSourceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

@Aspect
@Component
@Slf4j
public class DBTransactionalAspect {

    @Value("${spring.datasource.default-db-key}")
    private String defaultDbKey;


    @Pointcut("@annotation(com.gitee.huanminabc.utils_tools.dynamic_datasource.aop.DBTransactional)")
    public void DBTransactional() {
    }
    public static final ThreadLocal> stack = new InheritableThreadLocal<>();
    public static final ThreadLocal> transaction = new InheritableThreadLocal<>();



    @Around("DBTransactional()")
    public Object dBTransactionalAnno(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        //存放事务管理器的栈
        Stack dataSourceTransactionManagerStack = new Stack<>();
        //存放事务的状态,每一个DataSourceTransactionManager 对应一个 TransactionStatus
        Stack transactionStatuStack = new Stack<>();
        stack.set(transactionStatuStack);
        transaction.set(dataSourceTransactionManagerStack);
        try {
            //开启事务
            if (!openTransaction(defaultDbKey)) {
                throw new UniversalException("开启事务失败");
            }
            //执行业务方法
            Object ret = thisJoinPoint.proceed();
            //如果没有异常,说明两个sql都执行成功,两个数据源的sql全部提交事务
            commit();
            return ret;
        } catch (Throwable e) {
            rollback();
            log.error(String.format("DBTransactionalAspect, method:%s-%s occors error:",
                    thisJoinPoint.getTarget().getClass().getSimpleName(), thisJoinPoint.getSignature().getName()), e);
            throw e;
        }finally {
            //清线程数据,否则会出现内存泄漏或者被其他线程复用的情况
            stack.remove();
            transaction.remove();
        }

    }

    /**
     * 开启事务处理方法
     */
    public static boolean openTransaction(String key) {
        //如果stack不为空,说明已经开启了事务,那么后面就可以添加事物管理器和事务状态
        if (stack.get()==null) {
            return false;
        }
        try {
            DynamicDataSourceService.switchDb(key);
            // 从Spring上下文中获取事务管理器
            DataSourceTransactionManager dataSourceTransactionManager =(DataSourceTransactionManager) SpringContextHolder.getBean(key);
            // 创建新的事务状态
            DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
            // 设置事务创建新事物
            defaultTransactionDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
            TransactionStatus transactionStatus = dataSourceTransactionManager
                    .getTransaction(defaultTransactionDefinition);
            // 将事务状态和事务管理器存入对应的栈中
            stack.get().push(transactionStatus);
            transaction.get().push(dataSourceTransactionManager);
        } catch (Exception e) {
            throw new UniversalException(e,"开启事务失败(检查key的连接是否通畅), key:{}",key);
        }
        return true;
    }

    /**
     * 提交处理方法
     */
    private   void commit() {
        // 循环,直到事务管理器栈为空
        while (! stack.get().isEmpty()) {
            // 从事务管理器栈和事务状态栈中分别弹出当前的事务管理器和事务状态
            // 提交当前事务状态
            transaction.get().pop()
                    .commit( stack.get().pop());
        }
    }


    /**
     * 回滚处理方法

     */
    private  void rollback() {
        // 循环,直到事务管理器栈为空
        while (!stack.get().isEmpty()) {
            // 从事务管理器栈和事务状态栈中分别弹出当前的事务管理器和事务状态
            // 回滚当前事务状态
            transaction.get().pop().rollback(stack.get().pop());
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy