前言
Spring-tx支持了诸多持久化框架的事务操作,例如:JPA、Hibernate以及mybatis、spring-jdbc等。这篇主要对 DataSourceTransactioManager (支持spring-jdbc和mybatis) 进行分析。包含注解开启事务、事务注解@Transactional的原理等。
简单介绍
spring-tx将事务管理抽象成3个主要的组件:
- PlatformTransactionManager:平台事务管理器,平行的还有个 ReactiveTransactionManager,都继承自 TransactionManager,先不做分析。子类如下:
- DataSourceTransactioManager 、 HibernateTransactioManager 、 JPATransactioManager :对主流持久化框架的支持。
- JtaTransactioManager :分布式事务支持。
- TransactionDefinition:事务定义信息,例如隔离级别、传播途径、事务超时时间、只读等。
- TransactionStatus:事务具体运行状态
隔离级别 | 含义 |
ISOLATION_DEFAULT | 使用后端数据库默认使用的隔离级别(Spring中默认选项) |
ISOLATION_READ_UNCOMMITTED
(读未提交)
|
可能出现所有并发问题,效率最高,但不可用! |
ISOLATION_READ_COMMITTED
(读已提交)
|
防止了脏读
但没有防止不可重复读以及幻读——oracle默认支持
|
ISOLATION_EPEATABLE_READ
(可重复读)
|
防止了脏读、不可重复读
但没有防止幻读--mysql默认支持
|
ISOLATION_SERIALIZABLE
(串行化)
|
即非并发的,所以不会出现任何并发问题。
易出现死锁,效率太低!不可用!
|
类型 | 说明 | 举例 |
PROPAGATION_REQUIRED |
支持当前事务
如果不存,就建一个(默认的)
|
A,B,如果A有事务,则B使用A事务。如果A没有事务,则B开启一个新的事务。(A,B在同一个事务中) |
PROPAGATION_SUPPORTS |
支持当前事务
如果不存在,就不使用事务
|
A,B,如果A有事务,则B就使用A的事务。如果A没有事务,则B就不使用事务 |
PROPAGATION_MANDATORY |
支持当前事务
如果不存在,抛出异常
|
A,B,如果A有事务,则B就使用A的事务。如果A没有事务,则B抛出异常 |
PROPAGATION_REQUIRES_NEW |
如果有事务存在
挂起当前事务,创建一个新的事务
|
A,B,如果A有事务,B将A的事务挂起,并重新创建一个事务(A,B不在一个事务中,两个事务互不影响) |
PROPAGATION_NOT_SUPPORTED |
以非事务方式运行
如果有事务存在,挂起当前事务
|
A,B,非事务方式运行,A有事务就挂起事务 |
PROPAGATION_NEVER |
以非事务方式运行
如果有事务存在,抛出异常
|
总是以非事务运行 |
PROPAGATION_NESTED | 如果当前事务存在,则嵌套事务执行 |
基于SavePonit技术。(保存点)
A,B,A有事务,A执行之后,将A事务执行之后的内容保存到SavePonit。B事务有异常的情况,用户需要自己设置事务是提交还是回滚到保存点
|
使用
- 注意:默认情况下Spring中的事务处理只对RuntimeException进行回滚。
编程式
<!--配置事务管理器-->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--配置事务管理的模版-->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager" />
</bean>
@Service
public class UserService {
@Autowired
private TransactionTemplate transactionTemplate;
public void transfer(final String out, final String in, final Double money){
transactionTemplate.execute(new TransactionCallbackWithoutResult(){
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
....
// 发生异常会进行事务回滚
int i = 1/0;
...
}
});
}
}
声明式
- 单个类配置,transactionAttributes可配置项有:PROPAGATION:事务传播行为; ISOLATION:事务隔离级别; readOnly:只读; -Exception:发生哪些异常事务回滚;+Exception:发生哪些异常事务不回滚。用逗号分隔。
- 这个就不具体介绍了,用的也不多。
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="userServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target" ref="userService" />
<property name="transactionManager" ref="txManager" />
<!--配置方法的传播行为、隔离级别等,用逗号隔开-->
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
-
切面配置,通过配置切点及增强Advisor,并进行关联,借助aop匹配,支持满足条件的多个方法被事务增强。
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--使用spring提供的tx:advice管理事务-->
<tx:advice id="txAdvice" transaction-manger="txManager">
<tx:attributes>
<!--
propagation:事务传播行为
isolation:事务隔离级别
read-only:只读
rollback-for:发生哪些异常回滚事务
no-rollback-for:发生哪些异常不回滚事务
time-out:过期
-->
<tx:method name="transfer" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!--配置切面-->
<aop:config>
<!--指定切面-->
<aop:pointcut id="pointcut1" expression="execution(* menghao.service.*.*(..))" />
<!--将切面与增强关联-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1" />
</aop:config>
- 注解事务:开启后使用@Transactional注解标识方法即可,常用。@EnableTransactionManagement开启事务其实跟下面配置起到了等同的效果。
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--支持注解事务-->
<tx:annotation-driven transaction-manager="txManager" />
源码
看过了怎样使用,接下来就开始分析事务的实现原理,从 @EnableTransactionManagement开始入手。首先来看下该注解的定义
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
/**
* false:优先JDK动态代理,代理类无接口使用ciglib;
* true:强制Ciglib代理
*/
boolean proxyTargetClass() default false;
/**
* 基于JDK代理的增强 还是 AspectJ增强
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* 指示在切点应用多个切面增强时,事务切面执行顺序
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
对应这个事务开启的注解,有一个对应的selector进行bean的注册。这里便是 TransactionManagementConfigurationSelector。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
// 根据注解设置选择具体注册的类
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
// 看是否有必要支持JTA规范
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
AutoProxyRegistrar 就不展开分析了,它的作用就是根据 @EnableTransactionManagement设置的 mode如果为PROXY,则注册InfrastructureAdvisorAutoProxyCreator类来对满足条件的对象自动创建代理。主要分析下PROXY模式:
PROXY模式
承接上面的,proxy模式除了引入了 AutoProxyRegistrar,另一个就是 ProxyTransactionManagementConfiguration。这个类作为一个配置类,会引入4个主要的bean:
- BeanFactoryTransactionAttributeSourceAdvisor:事务增强的 Advisor,内部包含了 TransactionAttributeSource实例以及的定义了具体的切点。
- AnnotationTransactionAttributeSource:对 @Transactional 注解解析的支持。
- 会被设置到 BeanFactoryTransactionAttributeSourceAdvisor。
- TransactionInterceptor:具体切面的执行者,可以看作是涵盖了事务的开启,判断事务需要提交还是回滚的主要逻辑。
- 会被设置到 BeanFactoryTransactionAttributeSourceAdvisor。
- TransactionalEventListenerFactory:这个类是在 ProxyTransactionManagementConfiguration父类 AbstractTransactionManagementConfiguration中引入的,为了支持 @TransactionalEventListener 的识别和创建。
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
// AnnotationTransactionAttributeSource
@Nullable
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
从切点的定义来看,使用匿名内部类的实现方式,将 Advisor中的 TransactionAttributeSource(这里实现就是 AnnotationTransactionAttributeSource)给到pointcut,接下来看下具体的切点定义:
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
// 类级别的过滤,使用内部类 TransactionAttributeSourceClassFilter
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 这里获取的是子类(匿名内部类)实现的 getTransactionAttributeSource的返回,也就是 AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
// 特定的类不匹配
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
PlatformTransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
// 获取事务元数据(比如 @Transactional)不为空,说明匹配成功
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
这里 AnnotationTransactionAttributeSource的源码也不展开分析了,它主要提供了事务注解的识别和解析动作,除了支持 spring的@Transactional,还支持JTA的 javax.transaction.Transactional ,EJB的 javax.ejb.TransactionAttribute。以及对这些注解的解析动作(getTransactionAttribute方法),以spring的@Transactional识别的条件举例:方法必须是publish、且方法或类上被@Transactional标识。
一旦切点匹配上了,接下来就要是切面事务增强逻辑的调用了(org.aopalliance.intercept.MethodInterceptor#invoke)。
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// 获取目标类
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 调用父类方法 invokeWithinTransaction
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
}
主要动作
调用父类的 invokeWithinTransaction方法,这里我们只分析 PlatformTransactionManager 类型的处理。主要分为几个主要步骤:
- 封装事务信息与当前线程绑定,并记录上一个事务信息。
- 切点方法异常处理/正常返回处理。
- 将事务信息与当前线程解绑,并把方法执行前上一个的事务信息与当前线程绑定。
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 获取事务元数据,为空说明所切到的方法没有识别到事务元数据(比如@Transactional)
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 通过元数据决定事务管理器,比如 org.springframework.transaction.annotation.Transactional.transactionManager可以指定
// 默认全局只能定义一个 TransactionManager
final TransactionManager tm = determineTransactionManager(txAttr);
// 省略 ReactiveTransactionManager类型的处理
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 定义切点方法的唯一身份标识,相当于起个string类型的名字用于区分
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// 封装事务信息并与当前线程绑定
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// 回调切点方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 异常处理
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 事务信息与当前事务解绑
cleanupTransactionInfo(txInfo);
}
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 正常返回的处理
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 省略 CallbackPreferringPlatformTransactionManager类型处理
}
}
封装事务信息
委托给 org.springframework.transaction.PlatformTransactionManager#getTransaction
@SuppressWarnings("serial")
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// 如果没有名称,使用之前创建的方法标识作为name
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 根据传播行为返回事务 or 新建事务
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
// 设置事务状态,并将创建的事务与当前线程绑定
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
异常处理
委托给 org.springframework.transaction.PlatformTransactionManager#rollback
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
}
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
// 如果是指定回滚的异常,则回滚
try {
// PlatformTransactionManager.rollback
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
}
else {
// 非回滚异常进行如下处理
// 如果设置了 RollbackOnly(),还是会回滚。否则提交
try {
// PlatformTransactionManager.commit
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
}
}
}
}
正常返回处理
委托给 org.springframework.transaction.PlatformTransactionManager#commit
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
从上面3个主要逻辑来看,主要的工作被封装在了 org.springframework.transaction.PlatformTransactionManager实现类中。接下来分析开头提到了 DataSourceTransactionManager实现,介绍它之前,先来看下他的抽象父类 org.springframework.transaction.support.AbstractPlatformTransactionManager,实现了逻辑的主体,子类只需要在需要定制的地方进行扩展即可。
AbstractPlatformTransactionManager
-
getTransaction
可大体分为当前有事务和无事务两条处理线,当前方法主要是无事务的处理逻辑,有事务的处理逻辑被封装在 handleExistingTransaction
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// 如果为空则使用默认实例:即传播途径默认 PROPAGATION_REQUIRED;隔离级别默认 ISOLATION_DEFAULT;超时时间默认 -1等
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 方法由子类扩展
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 之前存在了事务的逻辑处理
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(def, transaction, debugEnabled);
}
/************** 以下逻辑为:当前无事务的处理逻辑 ***********/
// 检测设置的事务超时时间是否合理
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
/**
* 传播行为设置为以下的处理
* - PROPAGATION_MANDATORY:当前事务不存在,抛出异常
*/
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
/**
* 传播行为设置为以为的处理
* - PROPAGATION_REQUIRED
* - PROPAGATION_REQUIRES_NEW
* - PROPAGATION_NESTED
*/
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 返回当前事务状态对象,连接等信息封装成 SuspendedResources
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
// 根据参数创建新的事务状态实例,子类扩展开始事务(doBegin)
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
/**
* 开头已经判断如果有事务,执行另一套分支,所以到这里就是无事务,剩下的3个也就没什么区分了:
* - PROPAFATION_SUPPORTS:支持当前事务;如果不存在,就不使用事务
* - PROPAFATION_NOT_SUPPORTED:以非事务方式运行, 如果有事务存在,挂起当前事务
* - PROPAFATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常
*/
else {
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
// 返回事务状态
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
当前执行前已经存在事务的处理:
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
// PROPAGATION_NEVER:有事务抛出异常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
// PROPAGATION_NOT_SUPPORTED:有事务则挂起
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
// PROPAGATION_REQUIRES_NEW:挂起当前事务,另创建一个新事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error beginEx) {
// 恢复挂起的线程:达到两个事务互不影响
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
// PROPAGATION_NESTED:如果有事务存在,则嵌套事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
// 通过 SavepointManager创建 savepoints
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
// 不支持savepoints机制,则通过嵌套的 begin和 commit/rollback调用实现
return startTransaction(definition, transaction, debugEnabled, null);
}
}
/**
* 能进入当前方法的前提就是有事务,所以剩下的两种传播类型可视为一种,即仍使用当前事务:
* PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务
* PROPAGATION_REQUIRED:支持当前事务,如果不存,就建一个(默认的)
*/
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
-
commit
public final void commit(TransactionStatus status) throws TransactionException {
// 判断事务状态是否为已完成,则抛出异常
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 是否设置了 rollback-only,如果设置了则回滚
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus, true);
return;
}
// 最后提交动作
processCommit(defStatus);
}
-
rollback
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
// 如果事务已完成则抛出异常
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 执行回滚
processRollback(defStatus, false);
}
针对以上出现的需要子类定制的方法,这里做一些逻辑的简述,全部以 DataSourceTransactionManager实现来简述,就不贴源码了:
- startTransaction:会调用doBegin,由子类扩展。
- 如果发现当前事务没有持有JDBC连接(即java.sql.Connection),则调用 DataSource进行创建,否则复用 JDBC连接,
- 获取其隔离级别,并强制设置为手动提交(即autoCommit为false)。
- 设置事务状态为激活(即transactionActive为true)
- 设置事务超时时间(非TIMEOUT_DEFAULT,即-1时才会设置)
- 如果是新创建的JDBC连接,还会同当前线程进行绑定。
- processCommit:
- 如果有 savepoint,则清空
- 如果当前的事务是新创建的,而不是复用之前已存在的事务,则调用doCommit进行提交
- 最后做一些清理重置工作
- processRollback:
- 如果有 savepoint,则回滚之该点。
- 如果当前的事务是新创建的,而不是复用之前已存在的事务,则调用doRollback进行回滚
- 最后同样是一些清理重置工作
总结
目前已经将Spring事务原理的大体逻辑分析完毕,个别细节点没有展开,如果后期有用到,再继续追加吧。
来源:oschina
链接:https://my.oschina.net/marvelcode/blog/3195379