Skip to content

Instantly share code, notes, and snippets.

@HydrangeaPurple
Created December 28, 2020 09:05
Show Gist options
  • Save HydrangeaPurple/03e805c200e995d2880b61d91f46e51e to your computer and use it in GitHub Desktop.
Save HydrangeaPurple/03e805c200e995d2880b61d91f46e51e to your computer and use it in GitHub Desktop.
多数据源事务切面
package com.tydic.utils.common.aspect;
import com.tydic.utils.common.annotation.MultiTransactional;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import java.util.Stack;
/**
* 多数据源事务
*
* @author 7le
*/
@Aspect
@Order(-7)
@Component
public class MultiTransactionalAspect {
private static final Logger logger = LoggerFactory.getLogger(MultiTransactionalAspect.class);
@Autowired
private ApplicationContext applicationContext;
@Around(value = "@annotation(multiTransactional)")
public Object around(ProceedingJoinPoint pjp, MultiTransactional multiTransactional) throws Throwable {
Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack = new Stack<>();
Stack<TransactionStatus> transactionStatusStack = new Stack<>();
Class<? extends Throwable>[] rollbackClass = multiTransactional.rollbackFor();
try {
if (!openTransaction(dataSourceTransactionManagerStack, transactionStatusStack, multiTransactional)) {
return null;
}
Object ret = pjp.proceed();
commit(dataSourceTransactionManagerStack, transactionStatusStack);
return ret;
} catch (Throwable e) {
if (rollbackClass.length > 0) {
for (Class<? extends Throwable> aClass : rollbackClass) {
if (aClass.isAssignableFrom(e.getClass())) {
rollback(dataSourceTransactionManagerStack, transactionStatusStack);
break;
}
}
} else {
rollback(dataSourceTransactionManagerStack, transactionStatusStack);
}
logger.error(String.format(
"MultiTransactionalAspect catch exception class: %s method: %s detail:", pjp.getTarget().getClass().getSimpleName(),
pjp.getSignature().getName()), e);
throw e;
}
}
private boolean openTransaction(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
Stack<TransactionStatus> transactionStatusStack, MultiTransactional multiTransactional) {
String[] transactionMangerNames = multiTransactional.value();
if (ArrayUtils.isEmpty(multiTransactional.value())) {
return false;
}
for (String beanName : transactionMangerNames) {
DataSourceTransactionManager dataSourceTransactionManager = (DataSourceTransactionManager) applicationContext
.getBean(beanName);
TransactionStatus transactionStatus = dataSourceTransactionManager
.getTransaction(new DefaultTransactionDefinition());
transactionStatusStack.push(transactionStatus);
dataSourceTransactionManagerStack.push(dataSourceTransactionManager);
}
return true;
}
private void commit(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
Stack<TransactionStatus> transactionStatusStack) {
while (!dataSourceTransactionManagerStack.isEmpty()) {
dataSourceTransactionManagerStack.pop().commit(transactionStatusStack.pop());
}
}
private void rollback(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
Stack<TransactionStatus> transactionStatusStack) {
while (!dataSourceTransactionManagerStack.isEmpty()) {
dataSourceTransactionManagerStack.pop().rollback(transactionStatusStack.pop());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment