概览
首先我们通过@GlobalTransactional这个注解开启一个全局事务,而GlobalTransactionScanner.wrapIfNecessary()会为所有方法上加了这个注解的bean注入一个包装了GlobalTransactionalInterceptor实例的advisor,然后返回一个代理对象。GlobalTransactionalInterceptor会在该bean的方法调用前进行拦截,判断是否开启全局事务
上源码,关键位置我打了注释
@Override
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//判断全局事务是否启用
if (disableGlobalTransaction) {
return bean;
}
try {
synchronized (PROXYED_SET) {
if (PROXYED_SET.contains(beanName)) {
return bean;
}
interceptor = null;
//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));
} else {
Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
//判断bean里的方法上有没有@GlobalTransactional注解
if (!existsAnnotation(new Class[]{serviceInterface})
&& !existsAnnotation(interfacesIfJdk)) {
return bean;
}
if (interceptor == null) {
//初始化Interceptor,后面会注入代理对象
interceptor = new GlobalTransactionalInterceptor(failureHandlerHook);
ConfigurationFactory.getInstance().addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, (ConfigurationChangeListener) interceptor);
}
}
//判断当前bean是否已被aop代理过,比如说方法上加了@Transactional就会被spring代理
//如果没有被代理,调用父类的模板方法进行代理,advisor通过被重写的
//getAdvicesAndAdvisorsForBean返回上面的interceptor进行包装
if (!AopUtils.isAopProxy(bean)) {
bean = super.wrapIfNecessary(bean, beanName, cacheKey);
} else {
AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);
//把GlobalTransactionalInterceptor包装成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[]
return new Object[]{interceptor};
}
@Override
public void afterPropertiesSet() {
if (disableGlobalTransaction) {
if (LOGGER.isInfoEnabled(

本文分析了Seata全局事务的开启过程,从@GlobalTransactional注解开始,通过GlobalTransactionScanner和GlobalTransactionalInterceptor的角色,详细解释了如何创建代理对象并拦截方法调用。在事务开始时,GlobalTransaction的init和begin方法被调用,同时通过TransactionHookManager注册的hook可以在事务开始前后执行自定义操作。XID的传递主要在SeataFeignClient中完成,将XID放入请求头传递给下游服务,并通过SeataHandlerInterceptor在Spring MVC的拦截器链中捕获和使用。
最低0.47元/天 解锁文章
4185

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



