Spring 声明式事务源码流程
2023-02-19 16:18:58 0 举报
Spring声明式事务源码详细流程图
作者其他创作
大纲/内容
正常执行,事务提交commitTransactionAfterReturning(txInfo);
ProxyTransactionManagementConfiguration
提交txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
doSuspend
false
事务执行逻辑TransactionInterceptor.invoke()
true
外部存在事务时,传播属性为NEVER直接抛出异常throw new IllegalTransactionStateException
查找类上是否有@Transactional注解txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
提交processCommit(defStatus);
挂起事务,这里其实没有作用,传的是nullSuspendedResourcesHolder suspendedResources = suspend(null);
挂起外部事务Object suspendedResources = suspend(transaction);
根据@Transactional注解属性,开启事务status = tm.getTransaction(txAttr);
finally
上面这个注解会导入TransactionManagementConfigurationSelector这个类,该类继承ImportSelector,会在配置类解析阶段调用它的selectImports方法往Spring注册一系列的BeanDefinition
status.isNewTransaction() == true是一个新的事务才提交,否则不执行提交操作doCommit(status);
只是往TransactionSynchronizationManager的ThreadLocal中设置@Transactional上的属性信息,并不会开启事务prepareTransactionStatus()
从BeanFactory中拿到配置的事务管理器(DataSourceTransactionManager ),并转为PlatformTransactionManager final TransactionManager tm = determineTransactionManager(txAttr);PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
当存在外部事务时,挂起逻辑suspend(transaction)
方法事务信息对象return txObject
如果@Transactional注解上设置的传播属性为MANDATORY直接抛出异常throw new IllegalTransactionStateException
从TransactionSynchronizationManager中的ThreadLocal中拿取数据库连接ConnectionHolder ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
判断当前传播属性是否是NEVER
font color=\"#323232\
判断方法逻辑
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
Connection con = txObject.getConnectionHolder().getConnection();con.commit();
挂起外部事务SuspendedResourcesHolder suspendedResources = suspend(transaction);
当前传播属性是否是NOT_SUPPORTED
判断是否有挂起的事务if (status.getSuspendedResources() != null)
数据库进行回滚Connection con = txObject.getConnectionHolder().getConnection();con.rollback();
创建事务信息对象DataSourceTransactionObject txObject = new DataSourceTransactionObject();
移除线程ThreadLocal中的连接信息TransactionSynchronizationManager.unbindResource(this.dataSource);
创建BeanFactoryTransactionAttributeSourceAdvisor的Bean,会将上面生成的两个Bean设置到这个Bean中,创建一个Advisor,在Bean的初始化后阶段会根据这个Bean创建一个事务代理对象
AutoProxyRegistrar:继承ImportBeanDefinitionRegistrar,会在Spring启动过程的配置解析阶段执行registerBeanDefinitions,往Spring中注册一个BeanPostprocessor的Bean(InfrastructureAdvisorAutoProxyCreator),该BeanPostprocessor会在初始化后阶段进行支持事务的代理对象创建。ProxyTransactionManagementConfiguration:代理逻辑配置类,会配置生成一个BeanFactoryTransactionAttributeSourceAdvisor,也就是事务逻辑+筛选逻辑的实现,上面的BeanPostprocessor会根据这个Advisor的Bean对象创建支持事务的代理对象
@EnableTransactionManagement
只要类或者方法上匹配到一个@Transactional注解就表示需要进行事务动态代理if (txAttr != null) { return txAttr; }
创建AnnotationTransactionAttributeSource的Bean,会进行事务开启事务筛选,判断一个类是否开启事务,也就是是否加了@Transactional注解,相当于Pointcut
invokeWithinTransaction()
从线程中还原上一次的事务信息cleanupTransactionInfo(txInfo);
doCleanupAfterCompletion(status.getTransaction());
清除TransactionSynchronizationManager中事务的属性信息
返回连接信息return conHolder;
开启Spring事务需要做一些配置1. 在配置类上添加@EnableTransactionManagement注解2. 配置数据源,用来创建数据库连接3. 配置事务管理器,用来管理事务。管理数据库连接、数据库事务的开启、提交、回滚等操作
清除事务相关信息cleanupAfterCompletion(status);
执行业务逻辑,Sql代码retVal = invocation.proceedWithInvocation();
createTransactionIfNecessary
新的事务连接才进行回滚if(status.isNewTransaction())doRollback(status);
拿到事务属性信息,也是@Transactional注解的信息TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
清除事务信息对象中的连接txObject.setConnectionHolder(null);
真正执行挂起逻辑suspendedResources = doSuspend(transaction);
从配置的数据源中获取数据库连接Connection newCon = this.dataSource.getConnection();
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
创建数据库保存点,后续如果存在回滚可以根据这个保存点进行回滚控制status.createAndHoldSavepoint();
根据指定的异常进行回滚if(txInfo.transactionAttribute.rollbackOn(ex))
判断当前是否已经存在事务了if (isExistingTransaction(transaction))
回滚操作txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
cleanupAfterCompletion(status);
从ThreadLocal中移除连接信息ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(this.dataSource);
catch (Throwable ex)
创建事务信息对象Object transaction = doGetTransaction();
当前传播属性是否是REQUIRES_NEW
提交逻辑commitTransactionAfterReturning(txInfo);
创建TransactionInterceptor的Bean执行事务方法时,就会执行到这个类里面的invoke方法,相当于一个Advice
查找方法上是否有@Transactional注解TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
当前传播属性是否是NESTED
Spring 声明式事务开启、提交、回滚、隔离级别、传播机制等的实现逻辑
如果外部没有事务时 doGetTransaction()中拿不到ConnectionHolder ,这里为空不满足条件返回false如果外部存在事务,doGetTransaction()中可以拿到ConnectionHolder,并且开启了事务isTransactionActive()也成立 返回truetxObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive()
开启事务con.setAutoCommit(false);
如果有savepoint就回滚到savepoint点if (status.hasSavepoint())status.rollbackToHeldSavepoint();
InfrastructureAdvisorAutoProxyCreator的初始化后方法创建支持事务的代理对象
是否开启强制回滚if (defStatus.isLocalRollbackOnly())
doGetTransaction方法
判断当前传播属性def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY
往Spring注册一系列的BeanDefinitionselectImports()
判断当前传播属性是否是这三个中的其中一个REQUIRED/REQUIRES_NEW/PROPAGATION_NESTED
0 条评论
下一页