seata openfeign 实现传播xid源码解析
依赖
com.alibaba.cloud:spring-cloud-starter-alibaba-seata:2021.1
源码
- 自动配置
- 注册FEIGN对象包装器
- 注册BEAN后处理器,包装FeignClient
- 注册BEAN后处理器,包装FeignContext
com.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Client.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class SeataFeignClientAutoConfiguration {
...
@Configuration(proxyBeanMethods = false)
protected static class FeignBeanPostProcessorConfiguration {
// 处理FeignClient 对象
@Bean
SeataBeanPostProcessor seataBeanPostProcessor(
SeataFeignObjectWrapper seataFeignObjectWrapper) {
return new SeataBeanPostProcessor(seataFeignObjectWrapper);
}
// 处理FeignContext 对象
@Bean
SeataContextBeanPostProcessor seataContextBeanPostProcessor(
BeanFactory beanFactory) {
return new SeataContextBeanPostProcessor(beanFactory);
}
// FeignClient 对象包装器
@Bean
SeataFeignObjectWrapper seataFeignObjectWrapper(BeanFactory beanFactory) {
return new SeataFeignObjectWrapper(beanFactory);
}
}
...
}
- 包装FeignClient
使用SeataFeignBlockingLoadBalancerClient包装FeignBlockingLoadBalancerClient
使用SeataFeignClient包装其他Client
com.alibaba.cloud.seata.feign.SeataFeignObjectWrapper
Object wrap(Object bean) {
if (bean instanceof Client && !(bean instanceof SeataFeignClient)) {
if (bean instanceof FeignBlockingLoadBalancerClient) {
FeignBlockingLoadBalancerClient client = (FeignBlockingLoadBalancerClient) bean;
return new SeataFeignBlockingLoadBalancerClient(client.getDelegate(),
beanFactory.getBean(BlockingLoadBalancerClient.class),
beanFactory.getBean(LoadBalancerProperties.class),
beanFactory.getBean(LoadBalancerClientFactory.class),
this);
}
return new SeataFeignClient(this.beanFactory, (Client) bean);
}
return bean;
}
- 包装FeignContext
使用SeataFeignContext包装FeignContext
com.alibaba.cloud.seata.feign.SeataContextBeanPostProcessor
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof FeignContext && !(bean instanceof SeataFeignContext)) {
return new SeataFeignContext(getSeataFeignObjectWrapper(),
(FeignContext) bean);
}
return bean;
}
- SeataFeignClient
将XID写入header
com.alibaba.cloud.seata.feign.SeataFeignClient
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> seataXid = new ArrayList<>();
seataXid.add(xid);
headers.put(RootContext.KEY_XID, seataXid);
return Request.create(request.method(), request.url(), headers, request.body(),
request.charset());
}