Spring 源码分析之事务2 TransactionStatus与TransactionInfo

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 源码分析之事务2 TransactionStatus与TransactionInfo相关的知识,希望对你有一定的参考价值。

参考技术A

Spring 源码分析之事务
Spring 源码分析之事务2 TransactionStatus与TransactionInfo
Spring 源码分析之事务3 事务的提交与回滚

首先说一下两个类的作用:
TransactionStatus 以及子类:主要描述当前事务的状态,比如:是否有事务,是否是新事物,事务是否只读;回滚点相关操作等等。这些相关的属性在后面会影响事务的提交。
TransactionInfo 主要是持有事务的状态,以及上一个TransactionInfo 的一个引用,并与当前线程进行绑定。主要是为了保证当前请求持有的是自己的事务对象,根据自己的事务状态决定事务的提交与否。

该类结构图如下:

通过分析我们发现TransactionStatus接口的实现类抽象类AbstractTransactionStatus类主要完成以下功能:

如果想要使用事务的回滚相关操作,继承了 AbstractTransactionStatus 类的子类必须提供实现,否则在使用事务的回滚点相关操作的时候会抛出异常。

该类还完成了事务相关功能:

我们可以全局的看看DefaultTransactionStatus结构图:

AbstractTransactionStatus 中包含了3条属性:

所以 DefaultTransactionStatus 对象最终包含的信息有:

AbstractTransactionStatus 的完成的主要功能:

1.回滚点相关操作(是否有回滚点、设置回滚点、获取回滚点,创建回滚点)
2.标记事务已经完成

首先 protected TransactionInfo createTransactionIfNecessary 这个方法会返回一个TransactionInfo ,即在创建事务的时候,会返回。
如下:

查看prepareTransactionInfo()方法

此方法完成如下功能:

完整的类如下:
TransactionInfo 是抽象类TransactionAspectSupport的一个内部类

如果存在一个业务中法中调用多个其他业务,比如:ServiceA的a方法,调用了ServiceB的b方法和ServiceC的c方法。在调用ServiceB的和调用ServiceC的时候当前的事务对象是什么样子的,是和bindToThread()方法有关的,也就是和属性oldTransactionInfo 和持有transactionInfo的当前线程有关。
这里也可以继续关注一下 restoreThreadLocalStatus 方法。
没调用一个业务的时候,每个业务方法都有自己的TransactionInfo,每次执行的时候,都会把当前线程中的TransactionInfo取出来,然后新建自己的TransactionInfo,并在自己的TransactionInfo中,将刚刚取出来的TransactionInfo作为oldTransactionInfo 记录到自己的TransactionInfo中。然后每次执行完一个自己的业务逻辑执行,都会再次执行restoreThreadLocalStatus()方法,也就是将本地线程中的TransactionInfo设置为当前TransactionInfo中的oldTransactionInfo。保证每次执行自己的业务的时候,使用的是自己的TransactionInfo即可,保证事务对象不会发生错乱。

Spring事务源码分析总结

Spring事务是我们日常工作中经常使用的一项技术,Spring提供了编程、注解、aop切面三种方式供我们使用Spring事务,其中编程式事务因为对代码入侵较大所以不被推荐使用,注解和aop切面的方式可以基于需求自行选择,我们以注解的方式为例来分析Spring事务的原理和源码实现。

//配置事务管理器
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

注意:在需要开启事务的方法上加上@Transactional注解即可,这里需要注意的是,当tx:annotation-driven/标签在不指定transaction-manager属性的时候,会默认寻找id固定名为transactionManager的bean作为事务管理器,如果没有id为transactionManager的bean并且在使用@Transactional注解时也没有指定value(事务管理器),程序就会报错

TxNamespaceHandler

@Override
public void init() {
   //对tx:advice标签进行解析
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
//对annotation-driven标签进行解析
   registerBeanDefinitionParser("annotation-driven", new         AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}

AnnotationDrivenBeanDefinitionParser.parse()

    public BeanDefinition parse(Element element, ParserContext parserContext) {
registerTransactionalEventListenerFactory(parserContext);
       //对<tx:annotation-driven/> 标签的mode属性进行判断
String mode = element.getAttribute("mode");
if ("aspectj".equals(mode)) {
// mode="aspectj" 提供对aspectj方式进行事务的支持
registerTransactionAspect(element, parserContext);
}
else {
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}

AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//1.表示<tx:annoation-driven/>标签只会被解析一次,只有第一次才剩下
  AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
?
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
?
// Create the TransactionAttributeSource definition.
              //2.创建AnnotationTransactionAttributeSource
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
?
// Create the TransactionInterceptor definition.
               //3.创建TransactionInterceptor
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//注册事务管理器
               registerTransactionManager(element, interceptorDef);

               interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
?
// Create the TransactionAttributeSourceAdvisor definition.
               //4.创建BeanFactoryTransactionAttributeSourceAdvisor,并把前2个添加到属性中
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
               
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
               
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
?
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}

上面注册的三个Bean支持了整个事务的功能

 

registerAutoProxyCreatorIfNecessary()

    public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册InfrastructureAdvisorAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//设置proxy-target-class和expose-proxy的配置
       useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}

 

这两个方法的主要目的是注册InfrastructureAdvisorAutoProxyCreator ,这个类间接实现了BeanPostProcessor接口,我们知道,Spring会保证所有bean在实例化的时候都会调用其postProcessAfterInitialization方法,我们可以使用这个方法包装和改变bean,而真正实现这个方法是在其父类AbstractAutoProxyCreator类中:

//实例化userService的Bean就会调用此方法

postProcessAfterInitialization()

    @Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
           //根据给定的Bean的class和name构建出key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

wrapIfNecessary()

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
?
// Create proxy if we have advice.
       //获取指定Bean对应的增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//根据对应的增强器创建代理对象
           Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
?
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

 

 

 

registerTransactionManager()

    private static void registerTransactionManager(Element element, BeanDefinition def) {
def.getPropertyValues().add("transactionManagerBeanName",
TxNamespaceHandler.getTransactionManagerName(element));
}

getTransactionManagerName(element));

tx:annotation-driven/不指定属性的时候,默认去找id固定名为transactionManager的bean作为事务管理器

tatic final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";

	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";


	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}























































































































以上是关于Spring 源码分析之事务2 TransactionStatus与TransactionInfo的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码剖析-事务源码之@Transactionl解析

spring源码之事务上篇

1Springboot之事务&aop的核心功能源码分析

BlueStore源码分析之事物状态机

11Spring源码-分析篇-事务源码分析

11Spring源码-分析篇-事务源码分析