(1). spring-cloud-alibaba-seata-2.1.0.RELEASE(spring.factories)
查看seata是如何与Spring Boot结合的(找到入口文件):
spring-cloud-alibaba-seata-2.1.0.RELEASE.jar/META-INF/spring.factories
# SeataRestTemplateAutoConfiguration
# SeataHandlerInterceptorConfiguration
# SeataFeignClientAutoConfiguration
# SeataHystrixAutoConfiguration
# 以上四种,都是解决在不同环境(RestTemplate/MVC/Feign/Hystrix)情况下,把ThreadLocal中的TX_XID,传递给下一链路.
# Auto Configure
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
(2). SeataProperties
SeataProperties是Seata的配置信息载体.
@ConfigurationProperties("spring.cloud.alibaba.seata")
public class SeataProperties {
private String txServiceGroup;
public String getTxServiceGroup() {
return txServiceGroup;
}
public void setTxServiceGroup(String txServiceGroup) {
this.txServiceGroup = txServiceGroup;
}
}
(3). GlobalTransactionAutoConfiguration
package com.alibaba.cloud.seata;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import io.seata.spring.annotation.GlobalTransactionScanner;
@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;
}
@Bean
public GlobalTransactionScanner globalTransactionScanner() {
// 获得应用程序的名称
String applicationName = applicationContext.getEnvironment()
.getProperty("spring.application.name");
// 获得配置信息:spring.cloud.alibaba.seata.tx-service-group
String txServiceGroup = seataProperties.getTxServiceGroup();
// 如果没有配置该属性,则txServiceGroup=微服服务名称+-fescar-service-group
if (StringUtils.isEmpty(txServiceGroup)) {
// *************************************************************
// 微服务名称(account-service) + -fescar-service-group
// 例如:account-service-fescar-service-group
// 建议不要配置:spring.cloud.alibaba.seata.tx-service-group
// *************************************************************
txServiceGroup = applicationName + "-fescar-service-group";
seataProperties.setTxServiceGroup(txServiceGroup);
}
// ******************************************************************
// Seata的入口类
// ******************************************************************
return new GlobalTransactionScanner(applicationName, txServiceGroup);
}
}
(5). GlobalTransactionScanner继承结构图
(6). GlobalTransactionScanner.afterPropertiesSet
由于GlobalTransactionScanner实现了:InitializingBean, 所以,在Spring实例化对象之后,会回调:afterPropertiesSet方法.
// domain
private final AtomicBoolean initialized = new AtomicBoolean(false);
// methods
public void afterPropertiesSet() {
ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
(ConfigurationChangeListener)this);
if (disableGlobalTransaction) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Global transaction is disabled.");
}
return;
}
// ****************************************************
// 确保:afterPropertiesSet方法只运行一次
// ****************************************************
if (initialized.compareAndSet(false, true)) {
initClient();
}
}
(7). GlobalTransactionScanner.initClient
private void initClient() {
// ... ...
// **************************************************************
// 初始化:TM(事务管理器)
// **************************************************************
//init TM
TMClient.init(applicationId, txServiceGroup, accessKey, secretKey);
// **************************************************************
//init RM
// 初始化:RM(分支事务资源管理器)
// **************************************************************
RMClient.init(applicationId, txServiceGroup);
// ... ...
// 注册Spring关闭时的回调函数(钩子函数)
registerSpringShutdownHook();
}
(8). GlobalTransactionScanner.wrapIfNecessary
AbstractAutoProxyCreator.postProcessAfterInitialization会回调:GlobalTransactionScanner.wrapIfNecessary方法.
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
try {
synchronized (PROXYED_SET) {
if (PROXYED_SET.contains(beanName)) {
return bean;
}
interceptor = null;
// TCC代理处理
//check TCC proxy
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);
} else {
Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
// 如果类上或者接口上不包含:@GlobalTransactional或@GlobalLock
// 则直接返回到父类:AbstractAutoProxyCreator.postProcessAfterInitialization方法里.
if (!existsAnnotation(new Class[]{serviceInterface})
&& !existsAnnotation(interfacesIfJdk)) {
return bean;
}
// 代码能走到这里:代表类或者接口上有注解:@GlobalTransactional或@GlobalLock
if (interceptor == null) {
if (globalTransactionalInterceptor == null) {
// *********************************************************
// 创建:GlobalTransactionalInterceptor
// 后面留一节,专门讲解这里的逻辑
// *********************************************************
globalTransactionalInterceptor = new GlobalTransactionalInterceptor(failureHandlerHook);
ConfigurationCache.addConfigListener(
ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
(ConfigurationChangeListener)globalTransactionalInterceptor);
}
interceptor = globalTransactionalInterceptor;
}
}
LOGGER.info("Bean[{}] with name [{}] would use interceptor [{}]", bean.getClass().getName(), beanName, interceptor.getClass().getName());
// 如果这个对象不是一个代理对象.则通过:wrapIfNecessary方法进行AOP的代理.
if (!AopUtils.isAopProxy(bean)) {
bean = super.wrapIfNecessary(bean, beanName, cacheKey);
} else {
AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);
Advisor[] advisor = buildAdvisors(beanName, getAdvicesAndAdvisorsForBean(null, null, null));
for (Advisor avr : advisor) {
advised.addAdvisor(0, avr);
}
}
// 添加到临时集合中.
PROXYED_SET.add(beanName);
// 返回的是一个经过代理之后的bean
return bean;
}
} catch (Exception exx) {
throw new RuntimeException(exx);
}
} // end wrapIfNecessary
// AbstractAutoProxyCreator.wrapIfNecessary方法会回调该方法,获得要织入的代码逻辑(MethodInterceptor)
// AT模式下是:GlobalTransactionalInterceptor
// TCC模式下是:TccActionInterceptor
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource customTargetSource)
throws BeansException {
return new Object[]{interceptor};
} //end getAdvicesAndAdvisorsForBean
(9). 总结
GlobalTransactionScanner被Spring容器托管后,会做如下几件事:
- 初始化TM(事务管理器).
- 初始化RM(资源管理器).
- 扫描Spring容器里所有的Bean,如果Bean上有指定的注解(@GlobalTransactional/@GlobalLock),则,对这个Bean进行AOP代理.