在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(

最低0.47元/天 解锁文章
911

被折叠的 条评论
为什么被折叠?



