|
@@ -1,7 +1,9 @@
|
|
|
package com.gxzc.zen.orm.aop
|
|
|
|
|
|
+import com.gxzc.zen.common.util.SpringContextHolder
|
|
|
import com.gxzc.zen.orm.DynamicMultipleDataSource
|
|
|
import com.gxzc.zen.orm.annotation.DynamicDataSource
|
|
|
+import com.gxzc.zen.orm.annotation.MultiTransactional
|
|
|
import com.gxzc.zen.orm.contants.DSKey
|
|
|
import org.aspectj.lang.JoinPoint
|
|
|
import org.aspectj.lang.ProceedingJoinPoint
|
|
@@ -10,7 +12,10 @@ import org.aspectj.lang.reflect.MethodSignature
|
|
|
import org.slf4j.LoggerFactory
|
|
|
import org.springframework.core.annotation.Order
|
|
|
import org.springframework.stereotype.Component
|
|
|
+import org.springframework.transaction.jta.JtaTransactionManager
|
|
|
import java.lang.reflect.Method
|
|
|
+import kotlin.reflect.KClass
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
*
|
|
@@ -21,13 +26,14 @@ import java.lang.reflect.Method
|
|
|
@Order(-1) // 保证先于事务执行
|
|
|
@Component
|
|
|
class DataSourceSwitchAspect {
|
|
|
- init {
|
|
|
- logger.debug("${this::class.java.simpleName} initialized...")
|
|
|
- }
|
|
|
companion object {
|
|
|
private val logger = LoggerFactory.getLogger(DataSourceSwitchAspect::class.java)
|
|
|
}
|
|
|
|
|
|
+ init {
|
|
|
+ logger.debug("${this::class.java.simpleName} initialized...")
|
|
|
+ }
|
|
|
+
|
|
|
private var isAnnotationAspect = false
|
|
|
|
|
|
@Pointcut("execution(* com.gxzc.zen.api..*Service.*(..))")
|
|
@@ -46,11 +52,56 @@ class DataSourceSwitchAspect {
|
|
|
fun mpMapperPointCut() {
|
|
|
}
|
|
|
|
|
|
- @Pointcut("@annotation(com.gxzc.zen.orm.annotation.DynamicDataSource)")
|
|
|
- fun annotationCut() {
|
|
|
+ /**
|
|
|
+ * 一致性事务切面解决方案
|
|
|
+ */
|
|
|
+ @Around("@annotation(com.gxzc.zen.orm.annotation.MultiTransactional)")
|
|
|
+ fun multiTransactionAround(joinPoint: ProceedingJoinPoint): Any? {
|
|
|
+ logger.info("@MultiTransactional aspect...")
|
|
|
+ val methodName = joinPoint.signature.name
|
|
|
+ val parameterTypes = (joinPoint.signature as MethodSignature).method.parameterTypes
|
|
|
+ val method = joinPoint.target::class.java.getMethod(methodName, *parameterTypes)
|
|
|
+
|
|
|
+ if (method.isAnnotationPresent(MultiTransactional::class.java)) {
|
|
|
+ val multiTransaction = method.getAnnotation(MultiTransactional::class.java)
|
|
|
+ val transactionManager = SpringContextHolder.getBean(JtaTransactionManager::class.java)
|
|
|
+ val userTransaction = transactionManager?.userTransaction
|
|
|
+ return try {
|
|
|
+ userTransaction?.begin()
|
|
|
+ val r = joinPoint.proceed()
|
|
|
+ userTransaction?.commit()
|
|
|
+ return r
|
|
|
+ } catch (e: Throwable) {
|
|
|
+ val rollbackExceptions = multiTransaction.rollbackFor
|
|
|
+ val noRollbackExceptions = multiTransaction.noRollbackFor
|
|
|
+
|
|
|
+ val isRollbackExceptionPresent = isPresent(e, rollbackExceptions)
|
|
|
+ val isNoRollbackExceptionPresent = isPresent(e, noRollbackExceptions)
|
|
|
+
|
|
|
+ // rollbackFor回滚 noRollbackFor不回滚
|
|
|
+ if (isRollbackExceptionPresent || !isNoRollbackExceptionPresent) {
|
|
|
+ userTransaction?.rollback()
|
|
|
+ } else {
|
|
|
+ userTransaction?.commit()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return joinPoint.proceed()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断指定类型是否存在于注解中
|
|
|
+ * @param e 指定抛出类型
|
|
|
+ * @param exceptions 注解定义的类型列表
|
|
|
+ */
|
|
|
+ private fun isPresent(e: Throwable, exceptions: Array<KClass<out Throwable>>): Boolean {
|
|
|
+ return exceptions.find {
|
|
|
+ e::class.java.isAssignableFrom(it.java) || e::class.java == it::java
|
|
|
+ } != null
|
|
|
}
|
|
|
|
|
|
- @Around("annotationCut()")
|
|
|
+ @Around("@annotation(com.gxzc.zen.orm.annotation.DynamicDataSource)")
|
|
|
fun annotationAround(joinPoint: ProceedingJoinPoint): Any? {
|
|
|
logger.debug("@DynamicDatasource aspect...")
|
|
|
isAnnotationAspect = true
|