Created
December 28, 2020 09:05
-
-
Save HydrangeaPurple/03e805c200e995d2880b61d91f46e51e to your computer and use it in GitHub Desktop.
多数据源事务切面
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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