(1). 概述
在前面的内容,剖析到:TccActionInterceptor的代码织入,仅在消费端生效(@LocalTCC除外).
(2). TccActionInterceptor.invoke
public Object invoke(final MethodInvocation invocation) throws Throwable {
// 如果xid不存 或者 是否禁用全局事务 或者 是事为Saga分支
if (!RootContext.inGlobalTransaction() || disable || RootContext.inSagaBranch()) { // false
//not in transaction
return invocation.proceed();
}
// 获得远程方法信息
// io.seata.samples.tcc.transfer.action.FirstTccAction
// @TwoPhaseBusinessAction(name = "firstTccAction", commitMethod = "commit", rollbackMethod = "rollback")
// public boolean prepareMinus(
// BusinessActionContext businessActionContext,
// @BusinessActionContextParameter(paramName = "accountNo") String accountNo,
// @BusinessActionContextParameter(paramName = "amount") double amount);
Method method = getActionInterfaceMethod(invocation);
// 获得接口上的注解@TwoPhaseBusinessAction
TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class);
//try method
if (businessAction != null) { // 有注解@TwoPhaseBusinessAction才进该逻辑
//save the xid
// 获取ThreadLocal(RootContext)中的:
String xid = RootContext.getXID();
//save the previous branchType
// 获取ThreadLocal(RootContext)中的:BranchType
BranchType previousBranchType = RootContext.getBranchType();
// 如果不是TCC模型的话,设置为:TCC模型
//if not TCC, bind TCC branchType
if (BranchType.TCC != previousBranchType) {
RootContext.bindBranchType(BranchType.TCC);
}
// 在此处要稍微思考:
// 1. 分支事务什么时候注册?
// 答: 分支事务是在ActionInterceptorHandler.proceed方法里.
// 2. 分支事务什么时候commit/rollback?
// 答: commit和rollback都是由TC来驱动的.
// 3. 为什么没有catch异常做处理?
// 答: 所有的分支事务,被全局事务给包裹着,只要任何分支事务抛出了异常,会被全局事务给拦截,全局事务会告之TC,TC会驱动进行rollback.
try {
Object[] methodArgs = invocation.getArguments();
//Handler the TCC Aspect
// ************************************
// 3.1 获得目标对象和方法
// 3.2 actionInterceptorHandler.proceed()
// ActionInterceptorHandler类的内容,我留到下一节再剖析.
// ************************************
Map<String, Object> ret = actionInterceptorHandler.proceed(
method,
methodArgs,
xid,
businessAction,
// ************************************
// 3.1 获得目标对象和方法
// ************************************
invocation::proceed);
//return the final result
return ret.get(Constants.TCC_METHOD_RESULT);
}
finally {
// 如果不是TCC模型,还原成原来的模型(AT/Saga)
//if not TCC, unbind branchType
if (BranchType.TCC != previousBranchType) {
RootContext.unbindBranchType();
}
}
}
return invocation.proceed();
}// end invoke
(3). 总结
TccActionInterceptor的主要职责: 拦截消费者(Client)的调用,拦截方法上指定的注解(@TwoPhaseBusinessAction).