事务配置

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 开启声明式事务 --> <tx:annotation-driven /> <!-- 数据源信息 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name="driverClassName" value="org.h2.Driver"/> <!-- 数据库持久化存储为单个文件 --> <property name="url" value="jdbc:h2:file:~/.h2/test_db;DB_CLOSE_ON_EXIT=FALSE"/> <!-- 数据库只在内存中运行,关闭连接后数据库将被清空,适合测试环境--> <!-- <property name="url" value="jdbc:h2:mem:DBName;DB_CLOSE_DELAY=-1"/>--> <property name="username" value="sa"/> <property name="password" value=""/> </bean> <!-- 管理事务的类--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 业务类 --> <bean id="clientServer" class="org.springframework.jdbc.support.learning.transaction.ClientServerImpl" > <property name="dataSource" ref="dataSource" /> </bean> </beans>
一. 配置文件加载,初始化
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(Element)
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(Element,BeanDefinition)
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri)
org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve
org.springframework.transaction.config.TxNamespaceHandler#init
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
1. 解析事务配置节点信息。事务节点 <tx:annotation-driven />
2. 获取事务节点自定义命名空间解析处理器 TxNamespaceHandler。
http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler
3. TxNamespaceHandler 解析处理器初始化。依次注册事务通知相关的工具类。
TxAdviceBeanDefinitionParser 解析开启事务方法的配置解析类,并设置事务属性。配置比较麻烦,现在一般不使用。推荐使用注解

<!-- 配置事务的传播特性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="modify*" propagation="REQUIRED"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 那些类的哪些方法参与事务 --> <aop:config> <aop:pointcut id="allManagerMethod" expression="execution(* com.z2sci.soa.manager.*.*(..))"/> <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/> </aop:config>
AnnotationDrivenBeanDefinitionParser 开启事务相关的主要类注入。
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse(Element element, ParserContext parserContext)
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse(Element element, ParserContext parserContext)
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator(Element element, ParserContext parserContext)
org.springframework.aop.config.AopConfigUtils#registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object)
registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source)
(1). 注册事务代理类的创建工具类。 InfrastructureAdvisorAutoProxyCreator
(2). 注册事务管理的工具类。
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource: 事务属性注解的配置解析相关。
org.springframework.transaction.interceptor.TransactionInterceptor: 事务逻辑处理的主要类。继承 MethodInterceptor接口,aop代理类调用 invoke 方法,进行事务管理。
BeanFactoryTransactionAttributeSourceAdvisor 事务逻辑处理切点包装类 Advisor。 将事务属性配置(AnnotationTransactionAttributeSource) 和 事务逻辑处理类(TransactionInterceptor)关联起来。

/** * Inner class to just introduce an AOP framework dependency when actually in proxy mode. */ private static class AopAutoProxyConfigurer { public static void configureAutoProxyCreator(Element element, ParserContext parserContext) { 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. 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. 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. 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); } } }
JtaTransactionManagerBeanDefinitionParser JTA事务配置解析。
二. 在方法或类上的事务配置,创建事务代理类
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization(Object bean, String beanName)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary(Object bean, String beanName, Object cacheKey)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
1. 根据 bean 配置,获取事务的 拦截器。如果没找到事务拦截器,则不用生成事务代理类。
a. 获取所有AdvisorBean配置。 BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans()
b.查询满足条件的AdvisorBean 。事务默认满足条件的是 BeanFactoryTransactionAttributeSourceAdvisor。
判断主要逻辑:
org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor#pointcut切点的匹配方法。
org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches(Method method, Class<?> targetClass)
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#getTransactionAttribute(Method method, Class<?> targetClass)
最终依次寻找并解析目标方法,目标类,目标类父类或父接口上@Transactional 配置。没找到则不进行事务代理的创建。
org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(AnnotatedElement)
2. 生成事务管理的代理类。
a. 解析目标类的所有接口。
b. 将 公共拦截器 和 上步获取的拦截器合并。
c. 进一步判断 拦截器 是否满足 Advisor 规范。 Advisor, Advice, MethodInterceptor, MethodBeforeAdviceAdapter, AfterReturningAdviceAdapter, ThrowsAdviceAdapter
d. 创建代理类。事务默认使用 JdkDynamic 代理实现。生成代理和普通AOP实现类似。
三. 代理类调用业务方法,同时进行事务处理
这里以 JdkDynamic 代理逻辑进行分析。Cglib 代理有部分区别,但事务处理逻辑是使用同一个拦截器。
org.springframework.jdbc.support.learning.transaction.ClientServer#query(String sql)
org.springframework.aop.framework.JdkDynamicAopProxy#invoke(Object proxy, Method method, Object[] args)
org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
org.springframework.transaction.interceptor.TransactionInterceptor#invoke(MethodInvocation invocation)
1. 查询当前调用方法的 拦截器(Interceptor) 或 通知(Advice)。
通过事务切入点实现类 org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches(Method method, Class<?> targetClass)进行是否需要注入事务拦截器判断。事务切入点只处理 public 修饰的方法。org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute(Method method, @Nullable Class<?> targetClass)
最终获得的事务默认拦截器是 org.springframework.transaction.interceptor.TransactionInterceptor。
2. 通过 代理类实例,目标类实例, 目标类class, 调用方法,方法参数已经拦截器 创建 ReflectiveMethodInvocation 实例invocation。
3. 调用 org.springframework.aop.framework.ReflectiveMethodInvocation#proceed() 方法,在该方法中再调用事务处理方法
org.springframework.transaction.interceptor.TransactionInterceptor#invoke(MethodInvocation invocation)
四. 事务拦截器进行事务的逻辑处理
org.springframework.transaction.interceptor.TransactionInterceptor#invoke(MethodInvocation invocation)
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction(Method method, Class<?> targetClass,final InvocationCallback invocation)
1. 获得 事务属性资源信息(AnnotationTransactionAttributeSource) 实例。
2. 通过 事务属性资源信息 实例获取 目标方法 或 目标类上 事务属性(@Transactional)配置信息实例 txAttr。org.springframework.transaction.interceptor.RuleBasedTransactionAttribute
3. 通过 事务属性(@Transactional)配置信息 获取 事务管理类实例 tm。当前配置的事务管理器类: org.springframework.jdbc.datasource.DataSourceTransactionManager
4. 如果是 响应式事务(ReactiveTransactionManager),则进行相关处理。这里不进行响应事务的逻辑分析。
5. 将事务管理器 强制转换成 org.springframework.transaction.PlatformTransactionManager 类型 ptm。
6. 根据目标方法, 目标类 和 事务属性配置,获取事务切入点方法 信息 joinpointIdentification。org.springframework.jdbc.support.learning.transaction.ClientServerImpl.query
7. 根据 事务管理器(PlatformTransactionManager) ,事务属性配置信息(RuleBasedTransactionAttribute), 事务拦截点(joinpointIdentification) 创建 事务信息类(TransactionInfo) 实例 txInfo。事务提交时,根据 txInfo 进行事务提交和回滚。 这个单独分析。org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary(PlatformTransactionManager tm,TransactionAttribute txAttr, String joinpointIdentification)
8. 调用 org.springframework.transaction.interceptor.TransactionAspectSupport.InvocationCallback#proceedWithInvocation() 方法,最终调用目标方法。
9. 如果方法执行有异常,则进行异常处理。org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex)
10. 清理事务信息。 org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfo(@Nullable TransactionInfo txInfo)
11. 如果方法返回值 继承 io.vavr.control.Try 接口,则 执行 io.vavr.control.Try#onFailure(java.util.function.Consumer<? super Throwable>) 方法,判断是否需要设置事务回滚。
11. 事务提交处理,并返回目标方法方法值。 org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning(@Nullable TransactionInfo txInfo)
(一) 创建 事务信息类(TransactionInfo) 实例 txInfo
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction(Method method, Class<?> targetClass, InvocationCallback invocation)
org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary(PlatformTransactionManager tm,TransactionAttribute txAttr, String joinpointIdentification)
org.springframework.transaction.PlatformTransactionManager#getTransaction(@Nullable TransactionDefinition definition)
org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo(PlatformTransactionManager tm,
TransactionAttribute txAttr, String joinpointIdentification,TransactionStatus status)
1.设置事务属性(txAttr)名称 joinpointIdentification。即调用方法全名称。
2. 事务管理器(tm) 根据当前配置的事务配置属性(txAttr) 获取当前方法事务的状态。
org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction(@Nullable TransactionDefinition definition)
org.springframework.transaction.support.AbstractPlatformTransactionManager#doGetTransaction
org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction
org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction(TransactionDefinition definition, Object transaction,boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources)
org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareTransactionStatus(TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,boolean newSynchronization, boolean debug, @Nullable Object suspendedResources)
(1). 创建 事务对象实例 (transaction),以 Object 类型接受。
设置保存点标志为true。(如果是内嵌事务,出现异常时可以将事务回滚到保存点。)
设置数据库连接辅助类(ConnectionHolder)实例。 org.springframework.transaction.support.TransactionSynchronizationManager#getResource(Object key)
(2). 检测 创建的事务对象实例 (transaction) 是是否已存在。如果已存在,则按 已存在事务进行事务状态获取。
org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled)
a. 当前事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是 never 传播行为,则抛出异常。never 不容许在事务里面执行。
b. 当前事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是 not_supported传播行为,则挂起当前事务(挂起主要将当前事务的数据库连接信息置空),创建一个事务状态,标记为非新建事务。 如果是异步事务,则通过 TransactionSynchronizationManager 静态方法设置当前线程事务状态信息。
c. 当前事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是 requires_new 传播行为,则挂起当前事务,新开启一个事务状态。并设置数据库连接事务信息。org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin(Object transaction, TransactionDefinition definition) 。(1)通过数据源获取新连接(Connection);(2)设置连接(Connection)只读属性标记 和 事务隔离级别。(3)当连接(Connection)是自动提交时,设置为非自动提交。(4) 如果事务时只读,则通过连接(Connection),设置事务只读连接。(5)标记当前连接(Connection) 是激活的。(6) 设置事务超时时间。(7)如果是新建,则绑定连接(Connection)信息。TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder())
d. 当前事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是 nested 传播行为。(1)内嵌事务支持保存点,获得当前连接事务状态,创建保存点。底层通过数据库驱动设置。然后再返回 (2)不支持保存点,开启新事务状态返回。(这种情况主要是针对JTA的处理)
e. 其他 事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是 supports, required 传播行为,则 获得当前连接 事务状态信息,返回。
(3). 判断如果 当前事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是 mandatory传播行为,则抛出异常。 mandatory(必须在已存在的事务里面执行)
(4). 如果 当前事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是 required, requires_new, nested传播行为, 则挂起当前事情,并创建一个新的事务状态。
(5). 如果 当前事务配置属性(txAttr) (DelegatingTransactionDefinition#getPropagationBehavior())是其他传播特性,则 获得当前连接 事务状态信息,返回。
3. 通过事务管理器(tm), 事务配置属性(txAttr), 事务状态 (status) 去创建 事务信息实例(txInfo)。
org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo(PlatformTransactionManager tm,TransactionAttribute txAttr, String joinpointIdentification,TransactionStatus status)
(1) 使用 事务管理器(tm), 事务配置属性(txAttr), 目标方法标识 去创建 事务信息(TransactionInfo)实例 txInfo。
(2) 设置事务信息(txInfo)中 事务状态 (status)。
(3) 将当前事务信息(txInfo) 绑定到当前线程变量 ThreadLocal<TransactionInfo> transactionInfoHolder。
(二) 执行其他拦截器,AOP通知方法和业务方法。
TransactionAspectSupport.InvocationCallback#proceedWithInvocation()
(三) 如果方法执行有异常,则进行异常处理
org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex)
org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback(TransactionStatus status)
org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback(DefaultTransactionStatus status, boolean unexpected)
org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerBeforeCompletion(DefaultTransactionStatus status)
org.springframework.transaction.support.AbstractTransactionStatus#rollbackToHeldSavepoint
org.springframework.transaction.support.AbstractPlatformTransactionManager#doRollback(DefaultTransactionStatus status)
org.springframework.transaction.support.AbstractPlatformTransactionManager#doSetRollbackOnly(DefaultTransactionStatus status)
org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus)
org.springframework.transaction.support.AbstractPlatformTransactionManager#cleanupAfterCompletion(DefaultTransactionStatus status)
1.根据事务状态(status) ,判断事务是否已经提交。如果已经提交,则抛出异常。
2. 触发事务完成之前的事件处理。AbstractPlatformTransactionManager#triggerBeforeCompletion(DefaultTransactionStatus status)
3. 如果事务状态(status),有保存点信息,则事务回滚到到保存点。底层调用数据库的事务回滚保存点处理机制。AbstractTransactionStatus#rollbackToHeldSavepoint()
4. 如果事务状态(status) 是新建事务,则直接回滚事务。底层调用数据库的事务回滚机制。AbstractPlatformTransactionManager#doRollback(DefaultTransactionStatus status)
5. 否则 只有 事务状态(status) ,则设置事务为回滚标记(rollback-only)。
6. 触发事务完成之后的事件处理。AbstractPlatformTransactionManager#triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus)
7. 清理事务完成后 事务状态(status) 信息。AbstractPlatformTransactionManager#cleanupAfterCompletion(DefaultTransactionStatus status)
(1) 事务状态(status) 标记事务完成。(2)事务状态(status) 是新异步事务,清理异步事务管理器。(TransactionSynchronizationManager.clear()) (3) 事务状态(status) 是新建事务,进行事务完成后,后置处理。a.接触绑定的数据源信息。b.恢复数据连接(Connection)为自动提交。c. 恢复连接(Connection)事务隔离级别,只读属性。d.释放连接(Connection)实例。 DataSourceTransactionManager#doCleanupAfterCompletion(Object transaction) 和 DataSourceTransactionManager#doBegin(Object transaction, TransactionDefinition definition) 对应。 (4)当 事务状态(status) 有挂起事务时,恢复原来挂起的事务。
(四) 清理事务信息(txInfo)
org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfo(@Nullable TransactionInfo txInfo)
当前线程变量 ThreadLocal<TransactionInfo> transactionInfoHolder 恢复成原来 事务信息(txInfo) 。
(五) 事务提交处理
org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning(@Nullable TransactionInfo txInfo)
org.springframework.transaction.support.AbstractPlatformTransactionManager#commit(TransactionStatus status)
org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit(DefaultTransactionStatus status)
1. 检查 事务状态(status) ,当前事务状态(status) 事务已经提交,如果已提交则抛出异常。
2. 如果 事务状态(status) 是回滚标记,则直接回滚当前事务。按回滚事务处理。
3. 如果 事务状态(status) 是全局回滚标记,并且全局事务回滚不容许提交,则回滚当前事务。按回滚事务处理。
4. 提交事务处理。
org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit(DefaultTransactionStatus status)
(1). 事务提交预处理。AbstractPlatformTransactionManager#prepareForCommit(DefaultTransactionStatus status)
(2). 触发事务提交前 处理方法。
AbstractPlatformTransactionManager#triggerBeforeCommit(DefaultTransactionStatus status)
TransactionSynchronizationUtils.triggerBeforeCommit(status.isReadOnly())
TransactionSynchronization#beforeCommit(boolean readOnly)
(3). 触发事务完成前的 处理方法。
AbstractPlatformTransactionManager#triggerBeforeCompletion(DefaultTransactionStatus status)
TransactionSynchronizationUtils.triggerBeforeCompletion()
TransactionSynchronization#beforeCompletion()
(4). 如果 事务有保存点信息,则释放事务保存点信息。底层由数据库驱动支持。
(5). 如果是新开启的事务,则提交事务。底层由数据库驱动支持。AbstractPlatformTransactionManager#doCommit(DefaultTransactionStatus status)
(6). 如果事务提交出现 TransactionException , RuntimeException , Error 异常 则回滚事务。调用事务回滚逻辑,或者设置事务回滚标记。
AbstractPlatformTransactionManager#doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex)
(7). 触发事务提交后 处理方法。
AbstractPlatformTransactionManager#triggerAfterCommit(DefaultTransactionStatus status)
TransactionSynchronizationUtils.triggerAfterCommit()
TransactionSynchronization#afterCommit()
(8). 触发事务提交完成后 处理方法。
AbstractPlatformTransactionManager#triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus)
TransactionSynchronizationManager.clearSynchronization();
TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus)
TransactionSynchronization#afterCompletion(int status)
(9). 清理事务完成后 事务状态(status) 信息。AbstractPlatformTransactionManager#cleanupAfterCompletion(DefaultTransactionStatus status)
事务的隔离级别 (isolation)
隔离级别 | 含义 |
---|---|
ISOLATION_DEFAULT | 使用后端数据库默认的隔离级别 |
ISOLATION_READ_UNCOMMITTED | 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读 |
ISOLATION_READ_COMMITTED | 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生 |
ISOLATION_REPEATABLE_READ | 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生 |
ISOLATION_SERIALIZABLE | 最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的 |
并发事务引起的问题
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务。并发虽然是必须的,但可能会导致一下的问题。
- 脏读(Dirty reads)——脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。
- 不可重复读(Nonrepeatable read)——不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间进行了更新。
- 幻读(Phantom read)——幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录。
事务的传播行为(propagation behavior)
传播行为 | 含义 |
---|---|
PROPAGATION_REQUIRED | 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务 |
PROPAGATION_SUPPORTS | 表示当前方法不需要事务上下文,但是如果当前上下文已存在事务的话,那么该方法会在这个事务中运行 |
PROPAGATION_MANDATORY | 表示该方法必须在已存在的事务中运行,如果当前事务不存在,则会抛出一个异常 |
PROPAGATION_REQUIRED_NEW | 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager |
PROPAGATION_NOT_SUPPORTED | 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager |
PROPAGATION_NEVER | 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常 |
PROPAGATION_NESTED | 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以设置保存点,独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务 |
事务失效场景
1. 方法不是 public 修饰的。在AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断,如果目标方法不是 public,则TransactionAttribute返回 null,即不支持事务。
2. 方法通过 final 修饰。无法重写,则无法添加事务支持。
3. 方法调用当前类的其他方法。
解决方法一: 在该 Service 类中注入自己。然后通过注入的代理对象调用方法。

@Servcie public class ServiceA { @Autowired prvate ServiceA serviceA; @Transactional(rollbackFor=Exception.class) public void save(User user) { queryData1(); queryData2(); serviceA.save2(user); } @Transactional(rollbackFor=Exception.class) public void save2(User user) { addData1(); updateData2(); } }
解决方法二: AOP代理开启配置,使用 AopContext.currentProxy() 获取代理对象,再去调用对应方法。
<aop:aspectj-autoproxy expose-proxy=“true”> 设置expose-proxy属性为true,将代理暴露出来,使用AopContext.currentProxy()获取当前代理

@Servcie public class ServiceA { @Transactional(rollbackFor=Exception.class) public void save(User user) { queryData1(); queryData2(); ((ServiceA)AopContext.currentProxy()).save2(user); } @Transactional(rollbackFor=Exception.class) public void save2(User user) { addData1(); updateData2(); } }
4. 没有使用 Spring 管理 bean 对象,无法生成事务代理。
5. 多线程调用,无法进行事务管理。
在特殊情况下,需要多线程优化,可以使用编程事务,模拟伪两阶段提交(2PC)实行。但主要两阶段提交缺陷,给手动修改数据留好日志。

public class MainTest { //是否可以提交 public static volatile boolean IS_OK = true; public static void main(String[] args) { //子线程等待主线程通知 CountDownLatch mainMonitor = new CountDownLatch(1); int threadCount = 5; CountDownLatch childMonitor = new CountDownLatch(threadCount); //子线程运行结果 List<Boolean> childResponse = new ArrayList<Boolean>(); ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < threadCount; i++) { int finalI = i; executor.execute(() -> { try { System.out.println(Thread.currentThread().getName() + ":开始执行"); // if (finalI == 4) { // throw new Exception("出现异常"); // } TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(1000)); childResponse.add(Boolean.TRUE); childMonitor.countDown(); System.out.println(Thread.currentThread().getName() + ":准备就绪,等待其他线程结果,判断是否事务提交"); mainMonitor.await(); if (IS_OK) { System.out.println(Thread.currentThread().getName() + ":事务提交"); } else { System.out.println(Thread.currentThread().getName() + ":事务回滚"); } } catch (Exception e) { childResponse.add(Boolean.FALSE); childMonitor.countDown(); System.out.println(Thread.currentThread().getName() + ":出现异常,开始事务回滚"); } }); } //主线程等待所有子线程执行response try { childMonitor.await(); for (Boolean resp : childResponse) { if (!resp) { //如果有一个子线程执行失败了,则改变mainResult,让所有子线程回滚 System.out.println(Thread.currentThread().getName()+":有线程执行失败,标志位设置为false"); IS_OK = false; break; } } //主线程获取结果成功,让子线程开始根据主线程的结果执行(提交或回滚) mainMonitor.countDown(); //为了让主线程阻塞,让子线程执行。 Thread.currentThread().join(); } catch (Exception e) { e.printStackTrace(); } } }
6. 数据库表不支持事务。
事务不回滚
1. 事务传播特性设置错误。
2. 自己捕获异常处理后,没有继续抛出异常。导致事务拦截器没有捕获到异常,无法回滚。
3. 手动抛出的异常不在配置或默认的回归异常范围内。
4. 嵌套事务回滚多了。 嵌套事务回滚后,部分事务管理器回继续抛出异常,这是先捕获内部事务异常,然后再做其他处理。

@Service public class UserService { @Autowired private UserMapper userMapper; @Autowired private RoleService roleService; @Transactional public void add(UserModel userModel) throws Exception { userMapper.insertUser(userModel); try { roleService.doOtherThing(); } catch (Exception e) { log.error(e.getMessage(), e); } } }
当遇到复杂情况,须手动控制事务时,可以用编程式事务精确控制。

@Autowired private TransactionTemplate transactionTemplate; public void save(final User user) { queryData1(); queryData2(); transactionTemplate.execute((status) => { addData1(); updateData2(); return Boolean.TRUE; })
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」