@EnableTransactionManagement 声明式事物,
在SpringBoot中不需要写这个注解,因为已经开启了启动配置spring-boot-autoconfigure-2.2.13.RELEASE.jar,在META-INF下的
spring.factories文件中配置了开启自动配置的类EnableAutoConfiguration=\TransactionAutoConfiguration
TransactionAutoConfiguration
两个注解类:
PlatformTransactionManager、HibernateJpaAutoConfiguration、DataSourceTransactionManagerAutoConfiguration
两个内部类:
TransactionTemplateConfiguration 事物模板配置类
EnableTransactionManagementConfiguration 开启事物管理器配置类,支持两种方式
CglibAutoProxyConfiguration 默认没有配置走他,说明注解在类上
JdkDynamicAutoProxyConfiguration
这两个方法上都由@EnableTransactionManagement,@@以上就是自动装配
@EnableTransactionManagement 事物通知方式AdviceMode:PROXY(默认)、ASPECTJ
@Import({TransactionManagementConfigurationSelector.class})
AutoProxyRegistrar
AopConfigUtils.registerAutoProxyCreatorIfNecessary
AopConfigUtils#registerAutoProxyCreatorIfNecessary
注册InfrastructureAdvisorAutoProxyCreator,父类中继承了InstantiationAwareBeanPostProcessor因此会在bean的生命周期回调,作用就是开启自动代理
ProxyTransactionManagementConfiguration
BeanFactoryTransactionAttributeSourceAdvisor 表示PointcutAdvisor
TransactionAttributeSource 表示Pointcut
AnnotationTransactionAttributeSource 在匹配时会检查类或者方法上是否有@Transaction注解
TransactionInterceptor 代理逻辑Advice
这里作用就是向spring容器中添加一个Advisor,有了Advisor,那么spring构造bean时就会查看当前bean是不是匹配所设置的Pointcut(也就是类或者方法上是否有@Transaction注解)。如果匹配则利用所设置的Adivice(TransactionInterceptor)进行AOP生产代理对象,@@以上通过spring后置处理器来触发完成
下面是aop初始化逻辑,这里也是一样,不同的是这里设置的callBack是TransactionInterceptor
AbstractAutowireCapableBeanFactory#doCreateBean 跟AOP一样bean的后置处理器,在bean实例化后会进行回调
initializeBean
applyBeanPostProcessorsAfterInitialization
AbstractAutoProxyCreator#postProcessAfterInitialization 执行后置处理器
AbstractAutoProxyCreator#wrapIfNecessary
getAdvicesAndAdvisorsForBean 获取需要被代理的类
AbstractAutoProxyCreator#createProxy 配置ProxyFactory
ProxyFactory#getProxy 选择jdk动态代理还是Cglib
CglibAopProxy#getProxy 这里以Cglib为例
Enhancer 构建Enhancer
设置Callback为 DynamicAdvisedInterceptor,它实现了MethodInterceptor;代理类会经过并执行intercept方法
前面内容有看不懂得可以看下aop的那篇文章
org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
// PointcutAdvisor
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
// Pointcut
advisor.setTransactionAttributeSource(transactionAttributeSource);
// Advice
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
org.springframework.transaction.interceptor.TransactionInterceptor#invoke 进入正题
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 代理对象执行事务逻辑
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
这里调用的是父类
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 如果transaction属性为null,则该方法为非事务处理。
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
// 获取正在执行方法上的@Transaction注解信息
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 获取正在执行方法上是否指定TransactionManager,没有则生成默认的TransactionManager
final TransactionManager tm = determineTransactionManager(txAttr);
// 下面情况暂时不考虑
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException(
"Unsupported annotated transaction on suspending function detected: " + method +
". Use TransactionalOperator.transactional extensions instead.");
}
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
method.getReturnType());
}
return new ReactiveTransactionSupport(adapter);
});
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}
// 事务管理器必须是PlatformTransactionManager
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 如果没有指定事务名就要当前方法签名作为事务名
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// 开始创建事务
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// 创建事务成功后继续执行拦截器链,这里会执行业务方法
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 执行业务方法出错,这里会先执行finally中的方法然后在抛出异常
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 如果没有出错也是先执行这里然后再进行提交
cleanupTransactionInfo(txInfo);
}
if (retVal != null && 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;
}
else {
Object result;
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
try {
Object retVal = invocation.proceedWithInvocation();
if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
return retVal;
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
}
1、getTransactionAttributeSource 获取注解信息
2、asPlatformTransactionManager 获取TransactionManager,必须是PlatformTransactionManager
3、methodIdentification 生成joinpointIdentification作为事物的名字
org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary 开始创建事务,构建TransactionInfo事物对象信息
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// 如果未指定名称,则将方法标识用作事务名称
// If no name specified, apply method identification as transaction 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) {
// 创建TransactionStatus对象子流程,并开启事务
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
// 封装一个TransactionInfo对象
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// 如果未提供事务定义,请使用默认值
// Use defaults if no transaction definition given.
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 创建事务对象,这里得到的事务对象中可能没有数据库链接
// org.springframework.jdbc.datasource.DataSourceTransactionManager.doGetTransaction
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);
}
// Check definition settings for new transaction.
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 如果当前事务不存在,则引发异常
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 挂起
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
// 构造一个TransactionStatus对象
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// 以非事务状态运行
// Create "empty" transaction: no actual transaction, but potentially synchronization.
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);
}
}
判断是否持有数据库连接
YES
判断传播机制
NO
判断传播机制
startTransaction 开始事物
doBegin
DataSourceTransactionManager#doBegin
设置数据库事物对象
设置数据库隔离级别
设置AutoCommit=false
设置数据库连接超时时间
prepareSynchronization 设置TransactionSynchronizationManager
org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// todo
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// 获取数据库连接并设置到
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
// 设置隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
txObject.setReadOnly(definition.isReadOnly());
// 设置数据库连接的AutoCommit为false
// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
// 关闭自动提交
con.setAutoCommit(false);
}
prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);
// 设置数据库超时时间
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// 把获得的数据库连接对象通过TransactionSynchronizationManager设置到当前线程的ThreadLocal中
// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
// 绑定到ThreadLocal中,key为数据库对象,value为连接信息
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction 得到事物对象
protected Object doGetTransaction() {
// 如果本次开始事务的当前线程是第一次开启事务,那么获得的事务对象中就没有数据链接
// 反之如果本次开启事务的线程中还有事务没提交,那么获得的事务对象中就有数据库链接
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
// 设置保存点
txObject.setSavepointAllowed(isNestedTransactionAllowed());
// 获取数据库链接
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification,
@Nullable TransactionStatus status) {
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
// We need a transaction for this method...
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
// The transaction manager will flag an error if an incompatible tx already exists.
txInfo.newTransactionStatus(status);
}
else {
// The TransactionInfo.hasTransaction() method will return false. We created it only
// to preserve the integrity of the ThreadLocal stack maintained in this class.
if (logger.isTraceEnabled()) {
logger.trace("No need to create transaction for [" + joinpointIdentification +
"]: This method is not transactional.");
}
}
// 数据库连接对象绑定到当前线程的ThreadLocal
// We always bind the TransactionInfo to the thread, even if we didn't create
// a new transaction here. This guarantees that the TransactionInfo stack
// will be managed correctly even if no transaction was created by this aspect.
txInfo.bindToThread();
return txInfo;
}
org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#bindToThread
private void bindToThread() {
// Expose current TransactionStatus, preserving any existing TransactionStatus
// for restoration after this transaction is complete.
this.oldTransactionInfo = transactionInfoHolder.get();
transactionInfoHolder.set(this);
}
proceedWithInvocation 执行业务方法
org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing 执行业务方法出错
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);
}
// 默认只有RuntimeException和Error才会执行回滚,否则还会继续提交
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
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 {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
// 继续提交
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.support.AbstractPlatformTransactionManager#rollback 需要回滚
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);
}
org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
// 触发同步器的BeforeCompletion
triggerBeforeCompletion(status);
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
// 回滚到保存点
status.rollbackToHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
// 调用数据库连接对象的Rollback
doRollback(status);
}
else {
// Participating in larger transaction
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
doSetRollbackOnly(status);
}
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
}
}
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
}
// 如果设置了全局的快速失败
// Unexpected rollback only matters here if we're asked to fail early
if (!isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
}
}
}
catch (RuntimeException | Error ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
// 触发同步器的AfterCompletion
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
// Raise UnexpectedRollbackException if we had a global rollback-only marker
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
}
finally {
cleanupAfterCompletion(status);
}
}
org.springframework.transaction.support.AbstractPlatformTransactionManager#cleanupAfterCompletion 检查是否有事务挂起
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
status.setCompleted();
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
if (status.isNewTransaction()) {
doCleanupAfterCompletion(status.getTransaction());
}
// 检查是否有事务挂起
if (status.getSuspendedResources() != null) {
if (status.isDebug()) {
logger.debug("Resuming suspended transaction after completion of inner transaction");
}
Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
// 恢复
resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
}
org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning 无异常情况下提交子流程
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());
}
}
org.springframework.transaction.support.AbstractPlatformTransactionManager#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;
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);
}
org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status);
// 触发同步器的BeforeCommit
triggerBeforeCommit(status);
// 触发同步器的BeforeCompletion
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
unexpectedRollback = status.isGlobalRollbackOnly();
status.releaseHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
unexpectedRollback = status.isGlobalRollbackOnly();
// 调用数据库连接的Commit
doCommit(status);
}
else if (isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = status.isGlobalRollbackOnly();
}
// Throw UnexpectedRollbackException if we have a global rollback-only
// marker but still didn't get a corresponding exception from commit.
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
}
}
catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
}
catch (TransactionException ex) {
// can only be caused by doCommit
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
}
else {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
}
throw ex;
}
catch (RuntimeException | Error ex) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
}
doRollbackOnCommitException(status, ex);
throw ex;
}
// Trigger afterCommit callbacks, with an exception thrown there
// propagated to callers but the transaction still considered as committed.
try {
// 触发同步器的AfterCommit
triggerAfterCommit(status);
}
finally {
// 触发同步器的AfterCompletion
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
finally {
cleanupAfterCompletion(status);
}
}
贴个分析步骤
TransactionInterceptor#invoke
TransactionAspectSupport#invokeWithinTransaction 这里调用的是父类
getTransactionAttribute 获取注解信息
asPlatformTransactionManager 获取TransactionManager,必须是PlatformTransactionManager
methodIdentification 生成joinpointIdentification作为事物的名字
createTransactionIfNecessary 开始创建事物
TransactionAspectSupport#createTransactionIfNecessary 构建TransactionInfo事物对象信息
getTransaction
AbstractPlatformTransactionManager#getTransaction
doGetTransaction
DataSourceTransactionManager#doGetTransaction 得到事物对象
判断是否持有数据库连接
YES
判断传播机制
NO
判断传播机制
startTransaction 开始事物
doBegin
DataSourceTransactionManager#doBegin
设置数据库事物对象
设置数据库隔离级别
设置AutoCommit=false
设置数据库连接超时时间
prepareSynchronization 设置TransactionSynchronizationManager
prepareTransactionInfo
TransactionAspectSupport.TransactionInfo#bindToThread 把数据库连接对象绑定到当前线程的ThreadLocal
proceedWithInvocation 执行业务方法
有异常
回滚事物子流程
需要回滚 - 触发同步器的beforeCompletion - 调用数据库连接对象的rollback - 触发同步器的afterCompletion - 判断是否有事物挂起 - 如果有就把挂起的事物重新设置到TransactionSynchronizationManager,并执行同步器的resume方法
无异常
提交子流程 - 触发同步器的beforeCommit - 触发同步器的beforeCompletion - 调用数据库连接对象的commit - 触发同步器的afterCommit - 触发同步器的afterCompletion - 判断是否有事物挂起 - 如果有就把挂起的事物重新设置到TransactionSynchronizationManager,并执行同步器的resume方法
1、获取注解信息、获取TransactionManager、生成事务的名字
2、开始创建事务,先判断数据库连接、传播机制,再开始事务然后设置数据库事务对象、数据库隔离级别、关闭自动提交、准备事务管理同步器。
3、执行业务方法
4、有异常就回滚事务子流程,同时检查是否有事务挂起等,无异常就提交事务子流程。
简易流程:
1、生成事务状态对象
2、事务doBegin,获取并将数据库连接设置到事务状态对象中
3、把事务信息设置到事务同步管理器中
4、执行业务逻辑方法
4.1 生成a事务状态对象,并且可以获取到当前线程中已经存在的数据库连接
4.2 判断出来当前线程中已经存在事务
4.3 如果需要新开始事务,就先挂起当前数据库连接,挂起就是把test事务信息从事务同步管理器中转移到挂起资源对象中,并把当前a事务状态对象中的数据库连接设置为null
4.4 a事务doBegin,新生成一个数据库连接,并设置到a事务状态对象中
4.5 把a事务信息设置到事务同步管理器中
4.6 执行a业务逻辑方法
4.7 利用a事务状态对象,执行提交
4.8 提交之后会恢复所挂起的事务,这里的恢复,其实只是把挂起资源对象中所保存的信息再转移回事务同步管理器中
5、继续执行业务逻辑方法
6、利用事务状态对象,执行提交