Seata AT模式源码解析(一) ------ GlobalTransactionalInterceptor

  在pom.xml添加以下内容,本文基于以下版本源码进行分析。

    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-seata</artifactId>
      <version>2.1.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>io.seata</groupId>
      <artifactId>seata-all</artifactId>
      <version>1.4.2</version>
    </dependency>

  直接看到spring-cloud-alibaba-seata-2.1.0.RELEASE.jar的spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.seata.rest.SeataRestTemplateAutoConfiguration,\
com.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration,\
com.alibaba.cloud.seata.GlobalTransactionAutoConfiguration,\
com.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration,\
com.alibaba.cloud.seata.feign.hystrix.SeataHystrixAutoConfiguration

  SeataRestTemplateAutoConfiguration用于支持restTemplate的远程调用,传递XID(全局事务id)

@Configuration
public class SeataRestTemplateAutoConfiguration {
	
	//SeataRestTemplateInterceptor交给Spring管理
	@Bean
	public SeataRestTemplateInterceptor seataRestTemplateInterceptor() {
		return new SeataRestTemplateInterceptor();
	}
	
	//依赖注入所有的RestTemplate
	@Autowired(required = false)
	private Collection<RestTemplate> restTemplates;
	
	//依赖注入拦截器
	@Autowired
	private SeataRestTemplateInterceptor seataRestTemplateInterceptor;

	@PostConstruct
	public void init() {
		if (this.restTemplates != null) {
			for (RestTemplate restTemplate : restTemplates) {
				List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>(
						restTemplate.getInterceptors());
				//添加了一个拦截器
				interceptors.add(this.seataRestTemplateInterceptor);
				restTemplate.setInterceptors(interceptors);
			}
		}
	}

}
public class SeataRestTemplateInterceptor implements ClientHttpRequestInterceptor {
	@Override
	public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes,
			ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
		HttpRequestWrapper requestWrapper = new HttpRequestWrapper(httpRequest);
		
		//获取XID(threadlocal)
		String xid = RootContext.getXID();

		if (!StringUtils.isEmpty(xid)) {
		    //如果有XID则设置到request的HttpHeaders中
			requestWrapper.getHeaders().add(RootContext.KEY_XID, xid);
		}
		
		return clientHttpRequestExecution.execute(requestWrapper, bytes);
	}
}

  SeataHandlerInterceptorConfiguration实现了WebMvcConfigurer接口,添加了Interceptor去接收请求携带过来的XID

public class SeataHandlerInterceptorConfiguration implements WebMvcConfigurer {

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
	    //所有请求都拦截
		registry.addInterceptor(new SeataHandlerInterceptor()).addPathPatterns("/**");
	}
}
public class SeataHandlerInterceptor implements HandlerInterceptor {

	private static final Logger log = LoggerFactory
			.getLogger(SeataHandlerInterceptor.class);
	
	//调用到业务代码前,绑定XID
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
			Object handler) {
		
		//获取当前的XID
		String xid = RootContext.getXID();
		//获取请求携带过来的XID
		String rpcXid = request.getHeader(RootContext.KEY_XID);
		if (log.isDebugEnabled()) {
			log.debug("xid in RootContext {} xid in RpcContext {}", xid, rpcXid);
		}
		
		//当前没有XID,且请求携带了XID
		if (xid == null && rpcXid != null) {
		    //将rpcXid绑定到threadlocal中,则自己为该全局事务中的一员
			RootContext.bind(rpcXid);
			if (log.isDebugEnabled()) {
				log.debug("bind {} to RootContext", rpcXid);
			}
		}
		return true;
	}
	
	//调用完成结果返回以后,解绑XID
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
			Object handler, Exception e) {
		//获取请求携带的XID
		String rpcXid = request.getHeader(RootContext.KEY_XID);
		
		if (StringUtils.isEmpty(rpcXid)) {
			return;
		}
		
		//从threadlocal中移除XID
		String unbindXid = RootContext.unbind();
		if (log.isDebugEnabled()) {
			log.debug("unbind {} from RootContext", unbindXid);
		}
		if (!rpcXid.equalsIgnoreCase(unbindXid)) {
			log.warn("xid in change during RPC from {} to {}", rpcXid, unbindXid);
			if (unbindXid != null) {
				RootContext.bind(unbindXid);
				log.warn("bind {} back to RootContext", unbindXid);
			}
		}
	}
}

  GlobalTransactionAutoConfiguration主要实例化了GlobalTransactionScanner 这个bean

@Configuration
@EnableConfigurationProperties(SeataProperties.class)
public class GlobalTransactionAutoConfiguration {
	
	private final ApplicationContext applicationContext;

	private final SeataProperties seataProperties;

	public GlobalTransactionAutoConfiguration(ApplicationContext applicationContext,
			SeataProperties seataProperties) {
		this.applicationContext = applicationContext;
		this.seataProperties = seataProperties;
	}
	
	//实例化GlobalTransactionScanner
	@Bean
	public GlobalTransactionScanner globalTransactionScanner() {

		String applicationName = applicationContext.getEnvironment()
				.getProperty("spring.application.name");

		String txServiceGroup = seataProperties.getTxServiceGroup();

		if (StringUtils.isEmpty(txServiceGroup)) {
			txServiceGroup = applicationName + "-fescar-service-group";
			seataProperties.setTxServiceGroup(txServiceGroup);
		}
		
		return new GlobalTransactionScanner(applicationName, txServiceGroup);
	}
}

//获取spring.cloud.alibaba.seat.tx-service-group的属性
@ConfigurationProperties("spring.cloud.alibaba.seata")
public class SeataProperties {

	// todo support config Fescar server information

	/**
	 * Seata tx service group.default is ${spring.application.name}-fescar-service-group.
	 */
	private String txServiceGroup;

	public String getTxServiceGroup() {
		return txServiceGroup;
	}

	public void setTxServiceGroup(String txServiceGroup) {
		this.txServiceGroup = txServiceGroup;
	}

}

  SeataHystrixAutoConfiguration支持hytrix拦截器远程调用时的XID传递

@Configuration
@ConditionalOnClass(HystrixCommand.class)
public class SeataHystrixAutoConfiguration {

	@Bean
	SeataHystrixConcurrencyStrategy seataHystrixConcurrencyStrategy() {
		return new SeataHystrixConcurrencyStrategy();
	}

}
public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

	private HystrixConcurrencyStrategy delegate;

	public SeataHystrixConcurrencyStrategy() {
		this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
		HystrixPlugins.reset();
		HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
	}

	@Override
	public <K> Callable<K> wrapCallable(Callable<K> c) {
		if (c instanceof SeataContextCallable) {
			return c;
		}

		Callable<K> wrappedCallable;
		if (this.delegate != null) {
			wrappedCallable = this.delegate.wrapCallable(c);
		}
		else {
			wrappedCallable = c;
		}
		if (wrappedCallable instanceof SeataContextCallable) {
			return wrappedCallable;
		}

		return new SeataContextCallable<>(wrappedCallable);
	}

	private static class SeataContextCallable<K> implements Callable<K> {

		private final Callable<K> actual;
		private final String xid;

		SeataContextCallable(Callable<K> actual) {
			this.actual = actual;
			this.xid = RootContext.getXID();
		}

		@Override
		public K call() throws Exception {
			try {
				//绑定XID
				RootContext.bind(xid);
				//目标方法调用
				return actual.call();
			}
			finally {
				//清除threadlocal的XID
				RootContext.unbind();
			}
		}

	}
}

  SeataFeignClientAutoConfiguration用于支持feign远程调用的XID的传递

@Configuration
@ConditionalOnClass(Client.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class SeataFeignClientAutoConfiguration {
	
	@Bean
	@Scope("prototype")
	@ConditionalOnClass(name = "com.netflix.hystrix.HystrixCommand")
	@ConditionalOnProperty(name = "feign.hystrix.enabled", havingValue = "true")
	Feign.Builder feignHystrixBuilder(BeanFactory beanFactory) {
		return SeataHystrixFeignBuilder.builder(beanFactory);
	}
	
	@Bean
	@Scope("prototype")
	@ConditionalOnClass(name = "com.alibaba.csp.sentinel.SphU")
	@ConditionalOnProperty(name = "feign.sentinel.enabled", havingValue = "true")
	Feign.Builder feignSentinelBuilder(BeanFactory beanFactory) {
		return SeataSentinelFeignBuilder.builder(beanFactory);
	}
	
	@Bean
	@ConditionalOnMissingBean
	@Scope("prototype")
	Feign.Builder feignBuilder(BeanFactory beanFactory) {
		return SeataFeignBuilder.builder(beanFactory);
	}
	
	@Configuration
	protected static class FeignBeanPostProcessorConfiguration {
		
		//看这个BeanPostProcessor,用于包装feignClient传递XID
		@Bean	
		SeataBeanPostProcessor seataBeanPostProcessor(
				SeataFeignObjectWrapper seataFeignObjectWrapper) {
			return new SeataBeanPostProcessor(seataFeignObjectWrapper);
		}
		
		//将原本的feignContext包装为SeataFeignContext
		@Bean
		SeataContextBeanPostProcessor seataContextBeanPostProcessor(
				BeanFactory beanFactory) {
			return new SeataContextBeanPostProcessor(beanFactory);
		}
		
		//用于调用该SeataFeignObjectWrapper的wrap方法包装feignClient
		@Bean
		SeataFeignObjectWrapper seataFeignObjectWrapper(BeanFactory beanFactory) {
			return new SeataFeignObjectWrapper(beanFactory);
		}
	}

}

//SeataBeanPostProcessor 
final class SeataBeanPostProcessor implements BeanPostProcessor {

	private final SeataFeignObjectWrapper seataFeignObjectWrapper;

	SeataBeanPostProcessor(SeataFeignObjectWrapper seataFeignObjectWrapper) {
		this.seataFeignObjectWrapper = seataFeignObjectWrapper;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		//看这里,调用SeataFeignObjectWrapper的wrap方法包装feignClient
		return this.seataFeignObjectWrapper.wrap(bean);
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		return bean;
	}
}
Object wrap(Object bean) {
		//将原本的feignClient包装为SeataFeignClient
		//将原本的LoadBalancerFeignClient包装为SeataLoadBalancerFeignClient
		if (bean instanceof Client && !(bean instanceof SeataFeignClient)) {
			if (bean instanceof LoadBalancerFeignClient) {
				LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean);
				return new SeataLoadBalancerFeignClient(client.getDelegate(), factory(),
						clientFactory(), this.beanFactory);
			}
			return new SeataFeignClient(this.beanFactory, (Client) bean);
		}
		return bean;
}
//以SeataLoadBalancerFeignClient为例,重写父类LoadBalancerFeignClient的execute方法
@Override
	public Response execute(Request request, Request.Options options) throws IOException {
		//获取XID,放入request的headers中
		Request modifiedRequest = getModifyRequest(request);
		//feignClien正常调用
		return super.execute(modifiedRequest, options);
}
//如果有XID,将其封装到request中
private Request getModifyRequest(Request request) {
		
		String xid = RootContext.getXID();
		
		if (StringUtils.isEmpty(xid)) {
			return request;
		}

		Map<String, Collection<String>> headers = new HashMap<>(MAP_SIZE);
		headers.putAll(request.headers());

		List<String> fescarXid = new ArrayList<>();
		fescarXid.add(xid);
		headers.put(RootContext.KEY_XID, fescarXid);

		return Request.create(request.method(), request.url(), headers, request.body(),
				request.charset());
}

  来看到GlobalTransactionScanner 这个类,继承了AbstractAutoProxyCreator,重写了wrapIfNecessary方法和getAdvicesAndAdvisorsForBean方法

	@Override
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        try {
            synchronized (PROXYED_SET) {
                //已经处理过的bean不在去处理
                if (PROXYED_SET.contains(beanName)) {
                    return bean;
                }
                interceptor = null;
                //check TCC proxy
                //如果是TCC模式,TCC后续文章再讲解
                if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) {
                    //TCC interceptor, proxy bean of sofa:reference/dubbo:reference, and LocalTCC
                    interceptor = new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName));
                    ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
                        (ConfigurationChangeListener)interceptor);
                }
                //不是TCC模式
                else {
                    //bean可能已经生成过代理对象了
                    //获取目标类
                    Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
                    //获取目标接口
                    Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
					
					//判断目标类和或者目标接口的方法是否有GlobalTransactional或者GlobalLock注解
					//没有这种注解,直接返回。
                    if (!existsAnnotation(new Class[]{serviceInterface})
                        && !existsAnnotation(interfacesIfJdk)) {
                        return bean;
                    }
					
                    if (globalTransactionalInterceptor == null) {
                        //实例化GlobalTransactionalInterceptor
                        globalTransactionalInterceptor = new GlobalTransactionalInterceptor(failureHandlerHook);
                        ConfigurationCache.addConfigListener(
                            ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
                            (ConfigurationChangeListener)globalTransactionalInterceptor);
                    }
                    //globalTransactionalInterceptor赋值给interceptor
                    interceptor = globalTransactionalInterceptor;
                }
				
                LOGGER.info("Bean[{}] with name [{}] would use interceptor [{}]", bean.getClass().getName(), beanName, interceptor.getClass().getName());
                //如果不是生成过的代理对象
                if (!AopUtils.isAopProxy(bean)) {
                    //直接调用父类的方法
                    //父类再次调用到子类的getAdvicesAndAdvisorsForBean方法返回interceptor
                    //则该bean使用interceptor生成代理对象
                    bean = super.wrapIfNecessary(bean, beanName, cacheKey);
                } else {
                    //已经生成了代理对象了,只需要往拦截器链中放入interceptor就可以了
                    AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);
                    //调用自己的getAdvicesAndAdvisorsForBean方法返回interceptor
                    //调用父类的buildAdvisors将interceptor包装为advisor返回
                    Advisor[] advisor = buildAdvisors(beanName, getAdvicesAndAdvisorsForBean(null, null, null));
                    for (Advisor avr : advisor) { 
                    	//将自己的拦截逻辑放在最前面,第一个执行
                        advised.addAdvisor(0, avr);
                    }
                }
                PROXYED_SET.add(beanName);
                return bean;
            }
        } catch (Exception exx) {
            throw new RuntimeException(exx);
        }
	}
	@Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource customTargetSource)
            throws BeansException {
        //返回interceptor(GlobalTransactionalInterceptor)
        return new Object[]{interceptor};
	}

  看到GlobalTransactionalInterceptor,必然实现了MethodInterceptor接口,来看它的invoke方法

public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
		//获取到目标类
        Class<?> targetClass =
            methodInvocation.getThis() != null ? AopUtils.getTargetClass(methodInvocation.getThis()) : null;
        //可能是接口方法对象,获取目标实现类的方法对象
        Method specificMethod = ClassUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass);
        //非Object的方法
        if (specificMethod != null && !specificMethod.getDeclaringClass().equals(Object.class)) {
            //可能是桥接方法
            final Method method = BridgeMethodResolver.findBridgedMethod(specificMethod);
            //获取到GlobalTransactional注解信息
            final GlobalTransactional globalTransactionalAnnotation =
                getAnnotation(method, targetClass, GlobalTransactional.class);
            //获取到GlobalLock注解信息
            final GlobalLock globalLockAnnotation = getAnnotation(method, targetClass, GlobalLock.class);
            boolean localDisable = disable || (degradeCheck && degradeNum >= degradeCheckAllowTimes);
            if (!localDisable) {
            	//GlobalTransactional的具体执行逻辑
                if (globalTransactionalAnnotation != null) {
                    return handleGlobalTransaction(methodInvocation, globalTransactionalAnnotation);
                }
                //GlobalLock的具体执行逻辑
                else if (globalLockAnnotation != null) {
                    return handleGlobalLock(methodInvocation, globalLockAnnotation);
                }
            }
        }
        return methodInvocation.proceed();
    }
Object handleGlobalTransaction(final MethodInvocation methodInvocation,
        final GlobalTransactional globalTrxAnno) throws Throwable {
        boolean succeed = true;
        try {
            return transactionalTemplate.execute(new TransactionalExecutor() {
            	//目标方法调用
                @Override
                public Object execute() throws Throwable {
                    return methodInvocation.proceed();
                }
				
				//获取注解的name属性,没有的话,用方法名
                public String name() {
                    String name = globalTrxAnno.name();
                    if (!StringUtils.isNullOrEmpty(name)) {
                        return name;
                    }
                    return formatMethod(methodInvocation.getMethod());
                }
				
				//封装注解配置的属性到TransactionInfo中
                @Override
                public TransactionInfo getTransactionInfo() {
                    // reset the value of timeout
                    int timeout = globalTrxAnno.timeoutMills();
                    if (timeout <= 0 || timeout == DEFAULT_GLOBAL_TRANSACTION_TIMEOUT) {
                        timeout = defaultGlobalTransactionTimeout;
                    }
					
                    TransactionInfo transactionInfo = new TransactionInfo();
                    //全局事务超时时间,默认60000,配置文件全局指定client.tm.default-global-transaction-timeout(更多可配置属性,参考官网即可) 
                    transactionInfo.setTimeOut(timeout);
                    transactionInfo.setName(name());
                    //传播属性
                    transactionInfo.setPropagation(globalTrxAnno.propagation());
                    //全局锁冲突,重试间隔,配置文件全局指定client.rm.lock.retryInterval
                    transactionInfo.setLockRetryInternal(globalTrxAnno.lockRetryInternal());
                    //全局锁冲突,重试次数配,配置文件全局指定client.rm.lock.retryTimes
                    transactionInfo.setLockRetryTimes(globalTrxAnno.lockRetryTimes());
                    Set<RollbackRule> rollbackRules = new LinkedHashSet<>();
                    //控制回滚的异常条件
                    for (Class<?> rbRule : globalTrxAnno.rollbackFor()) {
                        rollbackRules.add(new RollbackRule(rbRule));
                    }
                    for (String rbRule : globalTrxAnno.rollbackForClassName()) {
                        rollbackRules.add(new RollbackRule(rbRule));
                    }
                    for (Class<?> rbRule : globalTrxAnno.noRollbackFor()) {
                        rollbackRules.add(new NoRollbackRule(rbRule));
                    }
                    for (String rbRule : globalTrxAnno.noRollbackForClassName()) {
                        rollbackRules.add(new NoRollbackRule(rbRule));
                    }
                    transactionInfo.setRollbackRules(rollbackRules);
                    return transactionInfo;
                }
            });
        } catch (TransactionalExecutor.ExecutionException e) {
        	//可以自己实现failureHandler接口,发生异常时,调用到自己的方法,比如发送邮件告警
            TransactionalExecutor.Code code = e.getCode();
            switch (code) {
                case RollbackDone:
                    throw e.getOriginalException();
                case BeginFailure:
                    succeed = false;
                    failureHandler.onBeginFailure(e.getTransaction(), e.getCause());
                    throw e.getCause();
                    
                //省略部分源码
                
            }
        } finally {
            if (degradeCheck) {
                EVENT_BUS.post(new DegradeCheckEvent(succeed));
            }
        }
}
public Object execute(TransactionalExecutor business) throws Throwable {
        // 1. Get transactionInfo
        //调用到getTransactionInfo获取事务信息
        TransactionInfo txInfo = business.getTransactionInfo();
        if (txInfo == null) {
            throw new ShouldNeverHappenException("transactionInfo does not exist");
        }
        // 1.1 Get current transaction, if not null, the tx role is 'GlobalTransactionRole.Participant'.
        //判断当前是否已经存在全局事务,如果已经处于全局事务中,则此时作为参与者加入全局事务中
        GlobalTransaction tx = GlobalTransactionContext.getCurrent();

        // 1.2 Handle the transaction propagation.
        //获取传播属性
        Propagation propagation = txInfo.getPropagation();
        //记录被挂起的全局事务
        SuspendedResourcesHolder suspendedResourcesHolder = null;
        try {
            switch (propagation) {
            
                //省略部分源码
                
                case REQUIRES_NEW:
                	//该情况下,要挂起之前的事务,新开启一个全局事务
                    // If transaction is existing, suspend it, and then begin new transaction.
                    if (existingTransaction(tx)) {
                        suspendedResourcesHolder = tx.suspend();
                        tx = GlobalTransactionContext.createNew();
                    }
                    // Continue and execute with new transaction
                    break;
                    
                //省略部分源码
                
                case REQUIRED:
                    //啥都不用做
                    // If current transaction is existing, execute with current transaction,
                    // else continue and execute with new transaction.
                    break;
                    
                //省略部分源码
                
            }
			
            // 1.3 If null, create new transaction with role 'GlobalTransactionRole.Launcher'.
            //XID为空情况下,第一次被调用开始,开启一个新的全局事务
            if (tx == null) {
                tx = GlobalTransactionContext.createNew();
            }

            // set current tx config to holder
            //设置txInfo封装为GlobalLockConfig并放入到threadlocal中
            //从threadlocal中返回之前存在的GlobalLockConfig
            GlobalLockConfig previousConfig = replaceGlobalLockConfig(txInfo);

            try {
                // 2. If the tx role is 'GlobalTransactionRole.Launcher', send the request of beginTransaction to TC,
                //    else do nothing. Of course, the hooks will still be triggered.
                // 事务开启
                beginTransaction(txInfo, tx);

                Object rs;
                try {
                    // Do Your Business
                    // 目标方法调用
                    rs = business.execute();
                } catch (Throwable ex) {
                    // 3. The needed business exception to rollback.
                    //方法调用过程发生异常,进行回滚
                    completeTransactionAfterThrowing(txInfo, tx, ex);
                    throw ex;
                }

                // 4. everything is fine, commit.
                //事务提交
                commitTransaction(tx);

                return rs;
            } finally {
                //5. clear
                //恢复之前存在的GlobalLockConfig
                resumeGlobalLockConfig(previousConfig);
                triggerAfterCompletion();
                cleanUp();
            }
        } finally {
            // If the transaction is suspended, resume it.
            if (suspendedResourcesHolder != null) {
                //如果有挂起的事务,需要恢复挂起的事务
                tx.resume(suspendedResourcesHolder);
            }
        }
}
Object handleGlobalLock(final MethodInvocation methodInvocation,
        final GlobalLock globalLockAnno) throws Throwable {
        return globalLockTemplate.execute(new GlobalLockExecutor() {
        	//目标方法调用
            @Override
            public Object execute() throws Throwable {
                return methodInvocation.proceed();
            }
			
			//全局锁冲突时,GlobalLock重试次数和重试间隔
            @Override
            public GlobalLockConfig getGlobalLockConfig() {
                GlobalLockConfig config = new GlobalLockConfig();
                config.setLockRetryInternal(globalLockAnno.lockRetryInternal());
                config.setLockRetryTimes(globalLockAnno.lockRetryTimes());
                return config;
            }
        });
}
public Object execute(GlobalLockExecutor executor) throws Throwable {
        boolean alreadyInGlobalLock = RootContext.requireGlobalLock();
        //将RootContext的CONTEXT_HOLDER(threadlocal)的TX_LOCK设置为true
        if (!alreadyInGlobalLock) {
            RootContext.bindGlobalLockFlag();
        }
		
        // set my config to config holder so that it can be access in further execution
        // for example, LockRetryController can access it with config holder
        //获取GlobalLock的重试属性
        GlobalLockConfig myConfig = executor.getGlobalLockConfig();
        //设置txInfo封装为GlobalLockConfig并放入到threadlocal中
        //从threadlocal中返回之前存在的GlobalLockConfig
        GlobalLockConfig previousConfig = GlobalLockConfigHolder.setAndReturnPrevious(myConfig);

        try {	
        	//目标方法调用
            return executor.execute();
        } finally {
			
            // only unbind when this is the root caller.
            // otherwise, the outer caller would lose global lock flag	
            if (!alreadyInGlobalLock) {
            	//将RootContext的CONTEXT_HOLDER(threadlocal)的TX_LOCK移除掉
                RootContext.unbindGlobalLockFlag();
            }

            // if previous config is not null, we need to set it back
            // so that the outer logic can still use their config
            if (previousConfig != null) {
                 //恢复之前存在的GlobalLockConfig
                GlobalLockConfigHolder.setAndReturnPrevious(previousConfig);
            } else {
                GlobalLockConfigHolder.remove();
            }
        }
}
public static GlobalTransaction getCurrent() {
        //获取XID
        String xid = RootContext.getXID();
        if (xid == null) {
        	//没有的话返回null
            return null;
        }
        //已经有了XID返回DefaultGlobalTransaction
        //GlobalTransactionRole.Participant事务的参与者
        //GlobalStatus.Begin开始状态
        return new DefaultGlobalTransaction(xid, GlobalStatus.Begin, GlobalTransactionRole.Participant);
}

public static GlobalTransaction createNew() {
        return new DefaultGlobalTransaction();
}
//xid为null,GlobalTransactionRole.Launcher事务的发起者,状态为UnKnown
DefaultGlobalTransaction() {
        this(null, GlobalStatus.UnKnown, GlobalTransactionRole.Launcher);
}

public SuspendedResourcesHolder suspend() throws TransactionException {
        // In order to associate the following logs with XID, first get and then unbind.
        //将当前的XID暂存到SuspendedResourcesHolder中
        String xid = RootContext.getXID();
        if (xid != null) {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Suspending current transaction, xid = {}", xid);
            }
            RootContext.unbind();
            return new SuspendedResourcesHolder(xid);
        } else {
            return null;
        }
}
public void resume(SuspendedResourcesHolder suspendedResourcesHolder) throws TransactionException {
		//将暂存的XID绑定回RootContext(threadlocal)中
        if (suspendedResourcesHolder == null) {
            return;
        }
        String xid = suspendedResourcesHolder.getXid();
        RootContext.bind(xid);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Resumimg the transaction,xid = {}", xid);
        }
}
private void beginTransaction(TransactionInfo txInfo, GlobalTransaction tx) throws TransactionalExecutor.ExecutionException {
        try {
        	//空方法,自己可以扩展,实现TransactionHook接口,通过registerHook方法注册自己的TransactionHook
            triggerBeforeBegin();
            tx.begin(txInfo.getTimeOut(), txInfo.getName());
            triggerAfterBegin();
        } catch (TransactionException txe) {
            throw new TransactionalExecutor.ExecutionException(tx, txe,
                TransactionalExecutor.Code.BeginFailure);

        }
}
public void begin(int timeout, String name) throws TransactionException {
		//如果不是事务发起者,直接返回
        if (role != GlobalTransactionRole.Launcher) {
            assertXIDNotNull();
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Ignore Begin(): just involved in global transaction [{}]", xid);
            }
            return;
        }
        assertXIDNull();
        //一般为空,事务发起者起始没有XID
        String currentXid = RootContext.getXID();
        if (currentXid != null) {
            throw new IllegalStateException("Global transaction already exists," +
                " can't begin a new global transaction, currentXid = " + currentXid);
        }
        //和seata服务端(TC)通信,获取XID
        //seata服务端 数据库持久化模式下,此时global_table就会插入该xid数据,控制和记录全局事务
        xid = transactionManager.begin(null, null, name, timeout);
        //状态修改为开始
        status = GlobalStatus.Begin;
 		//绑定XID到RootContext中,后续远程调用从这里获取到XID,放入request的header中。
        RootContext.bind(xid);
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Begin new global transaction [{}]", xid);
        }
}
//提交
private void commitTransaction(GlobalTransaction tx) throws TransactionalExecutor.ExecutionException {
        try {
            triggerBeforeCommit();
            tx.commit();
            triggerAfterCommit();
        } catch (TransactionException txe) {
            // 4.1 Failed to commit
            throw new TransactionalExecutor.ExecutionException(tx, txe,
                TransactionalExecutor.Code.CommitFailure);
        }
}
public void commit() throws TransactionException {
		//如果是事务的参与者,啥都不用干
        if (role == GlobalTransactionRole.Participant) {
            // Participant has no responsibility of committing
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Ignore Commit(): just involved in global transaction [{}]", xid);
            }
            return;
        }
        assertXIDNotNull();
       	//重试次数,在tm.commitRetryCount中配置,默认5次
        int retry = COMMIT_RETRY_COUNT <= 0 ? DEFAULT_TM_COMMIT_RETRY_COUNT : COMMIT_RETRY_COUNT;
        try {
            while (retry > 0) {
                try {
                    //这里向TC汇报,全局事务可以提交了。
                    status = transactionManager.commit(xid);
                    break;
                } catch (Throwable ex) {
                    LOGGER.error("Failed to report global commit [{}],Retry Countdown: {}, reason: {}", this.getXid(), retry, ex.getMessage());
                    retry--;
                    if (retry == 0) {
                        throw new TransactionException("Failed to report global commit", ex);
                    }
                }
            }
        } finally {
            if (xid.equals(RootContext.getXID())) {
                suspend();
            }
        }
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("[{}] commit status: {}", xid, status);
        }
}
public GlobalStatus commit(String xid) throws TransactionException {
		//新建全局提交请求
        GlobalCommitRequest globalCommit = new GlobalCommitRequest();
        //携带XID
        globalCommit.setXid(xid);
        //netty通信报告给TC
        GlobalCommitResponse response = (GlobalCommitResponse) syncCall(globalCommit);
        return response.getGlobalStatus();
}
//回滚
private void completeTransactionAfterThrowing(TransactionInfo txInfo, GlobalTransaction tx, Throwable originalException) throws TransactionalExecutor.ExecutionException {
        //roll back
        //判断抛出的异常是否和配置异常一致,没有配置则是Throwable类型
        if (txInfo != null && txInfo.rollbackOn(originalException)) {
            try {
            	//携带XID向告知TC全局事务需要回滚
                rollbackTransaction(tx, originalException);
            } catch (TransactionException txe) {
                // Failed to rollback
                throw new TransactionalExecutor.ExecutionException(tx, txe,
                        TransactionalExecutor.Code.RollbackFailure, originalException);
            }
        } else {
            // not roll back on this exception, so commit
            //提交
            commitTransaction(tx);
        }
}

  下一期,再去看到io.seata.rm.datasource.DataSourceProxy这个类的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值