1.简单使用
请参考如下链接:
tcc-transaction demo 例程源码
2.流程分析
我们根据例程代码分析,可以猜测到事务的执行流程通过spring-aop实现。
ResourceCoordinatorAspect,主要为了完成confirm和cancel的执行,其执行级别为HIGHEST_PRECEDENCE + 1;:
@Aspect
public abstract class ResourceCoordinatorAspect {
private ResourceCoordinatorInterceptor resourceCoordinatorInterceptor;
@Pointcut("@annotation(org.mengyun.tcctransaction.api.Compensable)")
public void transactionContextCall() {
}
@Around("transactionContextCall()")
public Object interceptTransactionContextMethod(ProceedingJoinPoint pjp) throws Throwable {
// 通过ConfigurableTransactionAspect的compensableTransactionInterceptor的事务相关初始化操作,执行函数逻辑
return resourceCoordinatorInterceptor.interceptTransactionContextMethod(pjp);
}
}
接下来是业务逻辑的执行
public Object interceptTransactionContextMethod(ProceedingJoinPoint pjp) throws Throwable {
// 从threadlocal中获取绑定的事务
Transaction transaction = transactionManager.getCurrentTransaction();
if (transaction != null) {
// 根据事务的状态判断,只有当Trying才会执行方法try(),confirm()
switch (transaction.getStatus()) {
case TRYING:
// 列出参与者,持久化
enlistParticipant(pjp);
break;
case CONFIRMING:
break;
case CANCELLING:
break;
}
}
return pjp.proceed(pjp.getArgs());
}
private void enlistParticipant(ProceedingJoinPoint pjp) throws IllegalAccessException, InstantiationException {
// 获取被注解标注的方法,即record()
Method method = CompensableMethodUtils.getCompensableMethod(pjp);
Compensable compensable = method.getAnnotation(Compensable.class);
// 通过反射获取confirm()和cancel()
String confirmMethodName = compensable.confirmMethod();
String cancelMethodName = compensable.cancelMethod();
// 获取当前事务
Transaction transaction = transactionManager.getCurrentTransaction();
// 生成事务唯一表示id
TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId());
if (FactoryBuilder.factoryOf(compensable.transactionContextEditor()).getInstance().get(pjp.getTarget(), method, pjp.getArgs()) == null) {
FactoryBuilder
.factoryOf(compensable.transactionContextEditor())
.getInstance()
// 往事务上下文写入参数,方便以后获取
.set(new TransactionContext(xid, TransactionStatus.TRYING.getId()), pjp.getTarget(), ((MethodSignature) pjp.getSignature()).getMethod(), pjp.getArgs());
}
Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes());
InvocationContext confirmInvocation = new InvocationContext(targetClass,
confirmMethodName,
method.getParameterTypes(), pjp