全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程

说起spring事务大家肯定都不陌生,在springboot项目中我们只需在需要事务控制的方法上面添加@Transactional注解即可,但是在springboot项目中使用事务,如下俩个注解不加也行。

  • @EnableAspectJAutoProxy:开启aop自动代理 默认为false(不加也行)
  • @EnableTransactionManagement:开启spring事务(@SpringBootApplication中已经为我们开启过了spring事务,不加也行)

spring事务:

  • 支持配置传播行为
  • 支持配置事务隔离级别
  • 支持按照指定异常回滚

@EnableTransactionManagement为我们的项目开启了spring事务,点进去

  • 此注解为我们导入了一个组件(TransactionManagementConfigurationSelector)

全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第1张图片

点进去发现TransactionManagementConfigurationSelector是一个importSelector,为ioc容器中注册了俩个bean (此处涉及到@import注解的知识)

  1. AutoProxyRegistrar:注册启动入口类
  2. ProxyTransactionManagementConfiguration:注册事务的切面、拦截器

点进去AutoProxyRegistrar最终会发现,里面的注册逻辑和@EnableAspectJAutoProxy注解注册入口类的逻辑是一模一样,我们暂时只需要知道AutoProxyRegistrar为我们注册了一个入口类即可

@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
     
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		/**
		 * AUTO_PROXY_CREATOR_BEAN_NAME:internalAutoProxyCreator
		 */
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
     
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
     
				/**
				 * 容器中存在的入口类
				 */
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				/**
				 * cls:当前要注册的入口类
				 * AnnotationAwareAspectJAutoProxyCreator优先级最高
				 * requiredPriority:当前要注册入口类的优先级
				 */
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
     
					/**
					 * 注册当前传进来的入口类
					 */
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}

		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

ProxyTransactionManagementConfiguration点进去,发现此类帮我们注册了三个bean (这些bean的调用涉及到aop调用流程相关知识点)

  1. TransactionInterceptor:拦截器,在aop执行的时候会先遍历此拦截器执行
  2. TransactionAttributeSource:搜集@Transaction注解上面的所有属性,封装成一个TransactionAttributeSource
  3. BeanFactoryTransactionAttributeSourceAdvisor:注册了一个advisor(事务切面,spring会为Advisor类型的对象生成代理对象
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
     

	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	/**
	 * 给容器中注册了一个bean:BeanFactoryTransactionAttributeSourceAdvisor
	 */
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
     
		/**
		 *生成一个事务的切面
		 */
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		/**
		 * 搜集@Transaction:注解上面的所有属性
		 */
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		/**
		 * 设置事务通知,涉及到aop调用链
		 */
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
     
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}
	/**
	 * 搜集@Transaction:注解上面的所有属性
	 */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
     
		return new AnnotationTransactionAttributeSource();
	}
	/**
	 * 设置事务通知,涉及到aop调用链
	 */
	@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;
	}

}

小结@EnableTransactionManagement
EnableTransactionManagement核心功能在于:给ioc注册了一个事务切面(advisor),切面中织入了通知(@Transactional),在每次调用事务方法之前会进行对事务的操作,继而才是执行目标方法。

不着急分析源码先来写一个小案例感受一下spring事务吧

@Service
public class UserServiceImpl implements UserService {
     
 @Autowired
 UserServiceImpl userService;

 @Transactional(propagation = Propagation.NEW)
 public void a() {
     
            this.update(new UpdateWrapper<User>().eq("id", 52).set("age", 100));
            System.out.println("a事务更新完毕");
            userService.b();
            userService.c();
            userService.d();
    }
}

上述的 UserServiceImpl 就是一个事务切面 ,其中的b()、c()、d()方法上都标注了@Transactional(propagation = Propagation.NEW) 注解,且方法里面依次更新 id 为53、54、55这些行的数据 并set age = 100。

编写测试类,当我们启动项目的时候访问我们的UserController中的test()接口继而触发 userService.a(); 就会依次执行更新操作,id从52 - 55的行数据的age 都会为100。

@RestController
@RequestMapping("/user")
public class UserController {
     
    @Autowired
    UserServiceImpl userService;

    @GetMapping("/test")
    public String test() {
     
        userService.a();
        return "ok";
    }

全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第2张图片

那如果我们在事务c这里抛出一个异常,其他事务依旧是原样的,执行的结果又会是怎么样呢?结果就是b更新成功,a、c、d更新失败

  • what fark you?不是说 REQUIRES_NEW 每次都是新建的一个事务的嘛!你c事务抛出异常关事务 a、c、d什么事讷?按理来说不是只有c更新失败,a、b、d更新成功嘛。问题先留着,涉及到源码
    全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第3张图片

反正b、c、d方法都是同一个类下面的,我这样调用行不行呢?答案是肯定不行!这样调用b、c、d上面的@Transactional注解都会失效。b、c、d都没有走UserServiceImpl这个事务切面,事务都会失效。
全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第4张图片

事务为什么会失效?

直接从此处断点,点进去发现和aop的执行流程一模一样。搞懂了aop的运行流程,对于搞懂事务的运行流程还是很轻松的。只是可能事务里面的逻辑大家还是不是很清楚而已。
全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第5张图片

userService.a() 的执行会来到这里,在调用a()中的逻辑前,会先拿到接着遍历代理对象中的拦截器链

果然还是熟悉的代码呀,挨个遍历调用拦截器中的invoke()方法,换言之就是执行a()前会先执行事务切面中的事务通知逻辑

接着点进invoke()方法就是我们的spring事务的调用源码了。

我直接一句好家伙,这一团密密麻麻的是个什么鬼东西,这个是我用maven依赖debug时的spring最新的源码,我以下贴的带注释的源码是基于spring 5.0源码来分析的。原理都一样spring5.0源码我自己写了注释,最新的没有克隆编译写注释

invokeWithinTransaction()

spring 5.0 中的invokeWithinTransaction()源码如下,简化大体步骤分为如下几块,

  1. createTransactionIfNecessary 开启事务
  2. retVal = invocation.proceedWithInvocation(); 火炬传递(开始执行事务方法)
  3. completeTransactionAfterThrowing(txInfo, ex); 对火炬传递过程中出现的异常进行回滚
  4. commitTransactionAfterReturning(txInfo); 对相关的连接进行commit操作
@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
     
		// If the transaction attribute is null, the method is non-transactional.
		/**
		 * 获取@Transaction注解上的源属性
		 */
		TransactionAttributeSource tas = getTransactionAttributeSource();
		/**
		 * tas理论上和txAttr差不多
		 */
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		/**
		 * 获取事务管理器
		 */
		final TransactionManager tm = determineTransactionManager(txAttr);
		/**
		 * TODO
		 */
		if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
     
			boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
			boolean hasSuspendingFlowReturnType = isSuspendingFunction &&
					COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());
			if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {
     
				throw new IllegalStateException("Coroutines invocation not supported: " + method);
			}
			CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);

			ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
     
				Class<?> reactiveType =
						(isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());
				ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
				if (adapter == null) {
     
					throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
							method.getReturnType());
				}
				return new ReactiveTransactionSupport(adapter);
			});

			InvocationCallback callback = invocation;
			if (corInv != null) {
     
				callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments());
			}
			/**
			 * 调用事务
			 */
			Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm);
			if (corInv != null) {
     
				Publisher<?> pr = (Publisher<?>) result;
				return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) :
						KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation()));
			}
			return result;
		}

		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) {
     
				// 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);
				}
			}
			/**
			 * 事务的提交,最里面其实也就是一个con.commit()
			 */
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
		/**
		 * 回滚类型的事务走这里,带指定回滚类型的事务
		 */
		else {
     
			Object result;
			final ThrowableHolder throwableHolder = new ThrowableHolder();
			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)) {
     
							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 {
     
							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;
		}
	}

createTransactionIfNecessary()

在这里插入图片描述
代码很长我尽量分析与spring事务关联紧密的代码就好了,关键代码createTransactionIfNecessary(),字面意思理解:如果必要创建一个事务?何为创建事务?可以剧透一下,简单的说其实就是关闭事务自动提交。点进去createTransactionIfNecessary()。

  • tm:我们配置的事务管理器
  • txAttr:事务注解上的属性

tm、txAttr不为null,来到getTransaction()点进去查看是如何获取事务的,

分析createTransactionIfNecessary之getTransaction()

getTransaction中的代码可以精简成如下几步理解

  1. 获取事务对象(每个事务的事务对象都是不同的,但是每个事务的事务对象中的contextholder可能相同)
  2. 判断当前事务对象是否是嵌套事务,如果是走嵌套事务执行逻辑
  3. 非嵌套事务,且事务的传播行为为PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED,都是执行startTransaction()
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
		throws TransactionException {
     

	// Use defaults if no transaction definition given.
	TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
	/**
	 * 获取一个事务对象
	 * 注意:第一次获取到的事务对象里面并没有连接,且 contextholder == null
	 */
	Object transaction = doGetTransaction();
	boolean debugEnabled = logger.isDebugEnabled();
	/**
	 * 嵌套事务的将会走此if分支
	 * 事务是否存在(当前的transaction事务对象是否是激活状态且存在ConnectionHolder那么此处为true)
	 */
	if (isExistingTransaction(transaction)) {
     
		/**
		 * 事务是否存在(当前的transaction事务对象是否是激活状态且ConnectionHolder!=null那么此处为true)
		 */
		return handleExistingTransaction(def, transaction, debugEnabled);
	}
	if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
     
		throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
	}
	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) {
     
		SuspendedResourcesHolder suspendedResources = suspend(null);
		if (debugEnabled) {
     
			logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
		}
		try {
     
			/**
			 * getTransaction--开启一个新事务
			 * 成功:获取事务成功
			 * 失败:获取事务失败
			 */
			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);
	}
}

哎呀又是一大坨代码,不过这里面的代码都挺重要的,着重分析!

分析getTransaction之doGetTransaction()

  • ⚠️每次都新建一个事务对象,给新建的事务对象中填充同一个线程中上个事务中的ConnectionHolder
@Override
	protected Object doGetTransaction() {
     
		/**
		 * 新建一个事务对象
		 */
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		/**
		 * 设置事务是否允许嵌套
		 */
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		/**
		 * 从threadlocal中获取连接对象(ConnectionHolder)
		 * 第一次获取到的ConnectionHolder为null
		 * obtainDataSource():DataSourceTransactionManager中配置过的数据源
		 */
		 ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		/**
		 * 事务对象中设置连接ConnectionHolder,ConnectionHolder中包含连接conection
		 */
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}

分析doGetTransaction之getResource()

点进来其实就是doGetResource(),从ThrealLocal(dataSource,contextHolder)中获取connectionHolder对象,第一个事务获取到的contextHolder为null

private static Object doGetResource(Object actualKey) {
     
		/**
		 * actualKey:DataSourceTransactionManager中配置过的数据源
		 * resources:ThreadLocal>
		 */
		Map<Object, Object> map = resources.get();
		/**
		 * 第一次肯定为null
		 */
		if (map == null) {
     
			return null;
		}
		/**
		 * 这个map的
		 * key:dataSource
		 * value:contextHolder
		 */
		Object value = map.get(actualKey);
		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
     
			map.remove(actualKey);
			if (map.isEmpty()) {
     
				resources.remove();
			}
			value = null;
		}
		/**
		 * 返回一个connectionHolder
		 */
		return value;
	}

分析getTransaction之startTransaction()

外层事务会走这里

  • ⚠️在事务开启之前标记当前事务是一个新事务, 然后才是真正的doBegin()开启事务
  • ⚠️提前剧透:通过startTransaction()方法开启的事务,状态、连接都是新的
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
											   boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
     
		/**
		 * getTransactionSynchronization:return this.transactionSynchronization(一个允许事务是否同步的标识符号)
		 * SYNCHRONIZATION_NEVER:事务永远不会同步
		 * 这俩个货不相等,那么开启一个新事务
		 */
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		/**
		 * ⚠️:newTransaction属性为new
		 * DefaultTransactionStatus:事务状态对象,
		 * suspendedResources:上一个事务的ConnectionHolder
		 */
		DefaultTransactionStatus status = newTransactionStatus(
				definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		/**
		 * startTransaction()->doBegin()
		 * 开启事务:其实也就是打开一个连接改变autoCommit的状态而已
		 */
		doBegin(transaction, definition);
		/**
		 *
		 */
		prepareSynchronization(status, definition);
		return status;
	}

分析startTransaction之doBegin()重点

doBegin代码很长,精简流程描述如下

  1. 判断事务对象中的connectionHolder属性是否为 null,为null标志着嵌套事务的连接与外层事务所用的连接不是同一个,这个关系到事务的回滚问题
  2. 获取事务对象中connectionHolder中的连接,设置自动提交为false
  3. 标记事务对象为激活状态
  4. 数据源与connectionHolde形成映射关系与线程一一进行绑定,存入threalLocal()中
protected void doBegin(Object transaction, TransactionDefinition definition) {
     
		/**
		 * 事务对象转型
		 */
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		Connection con = null;
		try {
     
			/**
			 * hasConnectionHolder: return(this.connectionHolder != null);
			 * isSynchronizedWithTransaction:return this.synchronizedWithTransaction;
			 */
			if (!txObject.hasConnectionHolder() ||
					txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
     
				/**
				 * 从数据源中获取连接
				 */
				Connection newCon = obtainDataSource().getConnection();
				if (logger.isDebugEnabled()) {
     
					logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
				}
				/**
				 * 给此时的事务对象设置一个ConnectionHolder进去,标记是一个新连接
				 */
				txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
			}
			/**
			 * 走到这的事务一般事务传播行为都是Propagation.REQUIRES_NEW
			 * 设置当前的ConnectionHolder允许事务同步,也就是允许嵌套事务都是一个新的事务
			 */
			txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
			/**
			 * 获取当前事务的连接对象
			 */
			con = txObject.getConnectionHolder().getConnection();
			/**
			 * 获取@Transaction注解中的事务隔离级别
			 */
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			/**
			 * 给事务对象设置传播行为
			 */
			txObject.setPreviousIsolationLevel(previousIsolationLevel);
			/**
			 * 给事务对象设置只读
			 */
			txObject.setReadOnly(definition.isReadOnly());
			if (con.getAutoCommit()) {
     
				/**
				 * 还原:自动提交为true
				 */
				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);
			}
			if (txObject.isNewConnectionHolder()) {
     
				/**
				 * 将ConnectionHolder与数据源进行一一绑定
				 * key:DataSource
				 * value:ConnectionHolder
				 */
				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);
		}
	}

分析getTransaction之handleExistingTransaction()

嵌套事务会走下面的代码,读者现在大致浏览一下下面的代码即可,下文有细说

private TransactionStatus handleExistingTransaction(
			TransactionDefinition definition, Object transaction, boolean debugEnabled)
			throws TransactionException {
     

		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
     
			throw new IllegalTransactionStateException(
					"Existing transaction found for transaction marked with propagation 'never'");
		}

		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() + "]");
			}
			/**
			 * 清空当前事务对象中的contextholder = null,执行这行代码说明,嵌套事务与原先事务使用的不是同一个连接对象
			 */
			SuspendedResourcesHolder suspendedResources = suspend(transaction);
			try {
     
				/**
				 * 开启一个新事务
				 */
				return startTransaction(definition, transaction, debugEnabled, suspendedResources);
			} catch (RuntimeException | Error beginEx) {
     
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}

		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() + "]");
			}
			/**
			 * 默认为true
			 */
			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.
				/**
				 * 设置不是最新的事务
				 */
				DefaultTransactionStatus status =
						prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
				/**
				 * 创建保存点
				 */
				status.createAndHoldSavepoint();
				/**
				 * ⚠️:直接return
				 */
				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.
				return startTransaction(definition, transaction, debugEnabled, null);
			}
		}
		/**
		 * 默认的事务传播行为:PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.用的是同一个连接,且嵌套的事务为旧的事务
		 */
		// Assumably PROPAGATION_SUPPORTS or 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);
	}

事务传播行为的定义,结合源码来分析一下这些定义吧
全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第6张图片

PROPAGATION_NEVER:直接抛出异常,存在嵌套事务立马抛出异常。鸡肋
在这里插入图片描述
PROPAGATION_NOT_SUPPORTED:挂起外层事务,标记此事务不是最新的事务,不是最新的事务不会进行提交操作。个人感觉好鸡肋这个,你不加事务注解不也一样吗。
全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第7张图片

PROPAGATION_REQUIRES_NEW:此种状态嵌套事务先是将事务对象中的connectionHolder设置为null,为的是在startTransaction()的时候,为当前事务开辟一个新的连接。(也就是上图定义的每次开启新的事务)

PROPAGATION_NESTED:设置回滚点,标记当前事务为非最新的事务,如果某个子事务回滚,外层事务并没有吞掉子事务的异常,那么会引起外层事务回滚,由于所有事务都是用的一个连接,那么外层事务回滚的效果就是造成所有事务的全部回滚


回滚点的位置
全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第8张图片

PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED :默认传播行为,标记事务状态为非新的。

PROPAGATION_REQUIRED与PROPAGATION_SUPPORTS的区别在于:

  • PROPAGATION_REQUIRED作用于外层事务下会进行startTransaction()操作(此时会开启一个全新的事务),作用于子事务只是标记事务状态为非新的
  • 而PROPAGATION_SUPPORTS只作用于子事务,标记事务状态为非最新的事务,

全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第9张图片

只是标记事务状态不是新的,相当于还是在最外层的事务中进行执行。加入外层事务是这个意思

最外层事务直接会开启一个新的事务

completeTransactionAfterThrowing()

在进行火炬传递的期间出现异常,那么会进行回滚操作。我们直接来看看spring是怎么回滚的,点进去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 {
     			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 {
     
				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;
				}
			}
		}
	}

分析completeTransactionAfterThrowing之rollback()

对事务状态进行了一个转型操作,接着processRollback(),点进去processRollback()接着看

@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);
	}

分析rollback之processRollback

仔细观察spring的回滚源码,大体简化步骤分为如下几步

  1. 如果当前要回滚的事务状态中存在回滚点,按照回滚点回滚
  2. 如果当前要回滚的事务状态被标记为是一个新事务,那么doRollback(status)
  3. ⚠️其他情况标记事务状态中的 rollbackonly = false,这里标记的rollbackonly是存在于ResourceHoldersupport类!!!!!!!!
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
     
		try {
     
			boolean unexpectedRollback = unexpected;

			try {
     
				triggerBeforeCompletion(status);
				/**
				 * 如果有回滚点,按照回滚点回滚
				 */
				if (status.hasSavepoint()) {
     
					if (status.isDebug()) {
     
						logger.debug("Rolling back transaction to savepoint");
					}
					status.rollbackToHeldSavepoint();
				}
				/**
				 * 如果是一个新的事务(存在事务且事务是最新的),回滚对应的这个新的事务中的DML语句
				 */
				else if (status.isNewTransaction()) {
     
					if (status.isDebug()) {
     
						logger.debug("Initiating transaction rollback");
					}
					doRollback(status);
				}
				else {
     
					// Participating in larger transaction
					if (status.hasTransaction()) {
     
						/**
						 * isLocalRollbackOnly:return rollbackOnly回滚部分
						 * isGlobalRollbackOnParticipationFailure:参与失败造成的全部回滚 return this.globalRollbackOnParticipationFailure;
						 */
						if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
     
							if (status.isDebug()) {
     
								logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
							}
							/**
							 * 设置rollbackOnly属性为true,在最外层事务提交的时候会触发回滚操作
							 */
							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;
			}

			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);
		}
	}

分析processRollback之doRollback()重点

从事务状态中获取到连接进行回滚操作

@Override
	protected void doRollback(DefaultTransactionStatus status) {
     
		/**
		 * 事务状态中获取对应的连接
		 */
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
		Connection con = txObject.getConnectionHolder().getConnection();
		if (status.isDebug()) {
     
			logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
		}
		try {
     
			/**
			 * 回滚对应连接中的数据
			 */
			con.rollback();
		} catch (SQLException ex) {
     
			throw translateException("JDBC rollback", ex);
		}
	}

commitTransactionAfterReturning(txInfo);

进行事务的提交操作,在这里面完成,点进去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());
	}
}

分析commitTransactionAfterReturning之commit()重点

⚠️在事务提交之前还有一次判断是否需要回滚的操作!,一般来说如果ResourceHolderSupport中的RollbackOnly属性被修改为true那么会进行回滚操作,反之接着才是提交操作

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;
		/**
		 * AbstractTransactionStatus.RollbackOnly是否为true,默认是false
		 */
		if (defStatus.isLocalRollbackOnly()) {
     
			if (defStatus.isDebug()) {
     
				logger.debug("Transactional code has requested rollback");
			}
			//回滚操作
			processRollback(defStatus, false);
			return;
		}
		/**
		 * shouldCommitOnGlobalRollbackOnly()默认返回false
		 * isGlobalRollbackOnly():ResourceHolderSupport中的RollbackOnly属性为true那么也会进行回滚操作
		 */
		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);
	}

分析commit之processCommit()

我这里就不贴代码了,有回滚点抹掉回滚点不进行事务提交操作、只有是新事务才会来进行提交的,到此spring事务的整个执行流程算是完结撒花了,别着急走,来看下下文的配套图文解说吧
全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第10张图片

嵌套事务简化版执行流程

全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第11张图片

事务失效场景具体分析

注意回滚操作是根据连接回滚的,commit的之前还有一次判断是否需要回滚。这俩点对于事务回滚的理解十分重要!。

 @Transactional(propagation = Propagation.NEW)
 public void a() {
     
            this.update(new UpdateWrapper<User>().eq("id", 52).set("age", 100));
            System.out.println("a事务更新完毕");
            userService.b();
            userService.c();
            userService.d();
    }

上述代码的运行流程用伪代码表示如下,嵌套事务简化版伪代码如下

有了这个伪代码,我们再来分析一下真实事务失效的场景吧!

@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void a() {
     
        this.update(new UpdateWrapper<User>().eq("id", 52).set("age", 100));
        System.out.println("a事务更新完毕");
        userService.b();
        userService.c();
        userService.d();
        //REQUIRES_NEW事务传播行为 : a失败,b、c、d成功
        //Propagation.NESTED事务传播行为 :a、b、c、d失败
        //throw new NullPointerException();
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void b() {
     
        this.update(new UpdateWrapper<User>().eq("id", 53).set("age", 100));
        System.out.println("b事务更新完毕");
        //REQUIRES_NEW事务传播行为 : a、b、c、d失败
        //Propagation.NESTED事务传播行为 :a成功,b、c、d失败
        //throw new NullPointerException();

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void c() {
     
        this.update(new UpdateWrapper<User>().eq("id", 54).set("age", 100));
        System.out.println("c事务更新完毕");
        //REQUIRES_NEW事务传播行为 : b成功,a、c、d失败
        //Propagation.NESTED事务传播行为 :a、b成功,c、d失败
        //throw new NullPointerException();
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void d() {
     
        this.update(new UpdateWrapper<User>().eq("id", 55).set("age", 100));
        System.out.println("d事务更新完毕");
        //REQUIRES_NEW事务传播行为 : b、c成功,a、d失败
        //Propagation.NESTED事务传播行为 :a、b、c成功,d失败
        //throw new NullPointerException();
    }

REQUIRES_NEW事务失效情况分析

事务a、b、c、d执行回滚情况如下。

执行结果 a事务 b事务 c事务 d事务
抛出异常
a事务 x y y y
b事务 x x x x
c事务 x y x x
d事务 x y y x
  • REQUIRES_NEW传播行为下面a、b、c、d开辟的事务都拥有各自独立的连接。

b事务抛出异常,为什么a、b、c、d事务都会进行回滚呢?

b事务抛出的异常具有传递性连着会被a事务捕获,因此a、b会回滚。因为b事务抛出异常后直接代码都不会在接着向下执行了,因此c、d事务压根执行不到,因此a、b、c、d事务都更新失败。同理验证上述表格的所有情况

Propagation.NESTED事务失效情况分析

事务a、b、c、d执行回滚情况如下。Propagation.NESTED虽说也是同一个线程中的事务共享同一个连接,但是会创建保存点,回滚也是根据回滚点进行回滚的

  • 如果不对a事务中的代码进行try{}catche(Exception e){}操作,那么无论是a抛出的异常,还是b、c、d抛出的异常也好,a、b、c、d事务都将会进行回滚,因为这四个事务使用的是同一个连接,

全面解读spring注解事务失效场景,伪代码+图文深度解析spring源码运行过程_第12张图片

此表格针对上图这种情况分析的

执行结果 a事务 b事务 c事务 d事务
抛出异常
a事务 x x x x
b事务 y x x x
c事务 y y x x
d事务 y y y x

为什么b事务抛出异常a事务不会回滚呢?为什么c、d事务回滚了?

  • 答:b事务抛出异常向上抛被空的try-catch给吞掉了,虽然a、b事务中是同一个连接但是是根据回滚点来进行回滚的,因此不会触发a事务的回滚操作,而b事务一旦被抛出异常,c、d压根就不会被执行了,因此b事务抛出异常,只有a能更新成功

同理分析只有c事务抛出异常的情况下,为什么a、b更新成功,c、d更新失败呢?

  • 答:a更新成功是因为,c将异常向上抛给a的时候,被a给吞掉了异常,并没有触发a事务对应的回滚操作
  • 事务b更新成功是因为,c与b虽然是同一个连接,但是c回滚是根据回滚点回滚的,只回滚事务c的部分,d更新失败是压根就执行不到d中的代码了

invokeWithinTransaction伪代码

invokeWithinTransaction {
     
			//获取@Transaction注解上的源属性
			TransactionAttributeSource tas = getTransactionAttributeSource();
			//tas理论上和txAttr差不多
			final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
			//获取事务管理器
			final TransactionManager tm = determineTransactionManager(txAttr);
			if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
     
				TransactionInfo txInfo = createTransactionIfNecessary {
     
					status = tm.getTransaction(txAttr);
					{
     
						
						
						
						// 获取一个事务对象,第一次获取到的事务对象里面并没有连接,且且ConnectionHolder = null
						Object transaction = doGetTransaction();
						{
     
							//新建一个事务对象
							DataSourceTransactionObject txObject = new DataSourceTransactionObject();
							//设置事务是否允许嵌套
							txObject.setSavepointAllowed(isNestedTransactionAllowed());
							//从threadlocal中获取连接对象(ConnectionHolder)、第一次获取到的ConnectionHolder为null
							ConnectionHolder conHolder = {
     
									/**
									 * actualKey:连接池中获取的数据源
									 * resources:ThreadLocal>
									*/
									Map < Object, Object > map = resources.get();
									/**
									 * 第一次肯定为null
									 */
									if (map == null) {
     
										return null;
									}
									/**
									 * ⚠️:这里只是放进去我们配置事务管理器中的数据源
									 *  key:dataSource
									 * value:contextHolder
									 */
									return map.get(obtainDataSource());
							}
							/**
							 * 事务对象中设置连接ConnectionHolder,ConnectionHolder对象包含conection属性
							 * ⚠️newConnectionHolde:false
							 */
							txObject.setConnectionHolder(conHolder, false);
							return txObject;
						}
						
						
						
						//事务是否存在(当前的transaction事务对象是否是激活状态且存在ConnectionHolder那么此处为true)
						if (isExistingTransaction(transaction)) {
     
							//⚠️嵌套事务走这里,且直接return
							return handleExistingTransaction(def, transaction, debugEnabled);
						}
						
						
						
						if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
								def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
								def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
     
							//true:开启事务成功,false:开启事务失败
							//此方法,默认嵌套事务都会开启一个新事务
							return startTransaction(def, transaction, debugEnabled, suspendedResources);
							{
     
								//开启事务,设置autoCommit = false。标记事务状态
								doBegin(transaction, definition);
								{
     
									/**
									 * hasConnectionHolder: return(this.connectionHolder != null);
									 * isSynchronizedWithTransaction:return this.synchronizedWithTransaction;
									 */
									//判断条件等同:connectionHolder == null || synchronizedWithTransaction
									//确保PROPAGATION_REQUIRES_NEW类型的事务嵌套依然会开辟新的连接
									if (!txObject.hasConnectionHolder() ||
											txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
     
												//⚠️:newConnectionHolde:true 
												//⚠️:这里为ConnectionHolde开辟了一个新的连接
										txObject.setConnectionHolder(new ConnectionHolder(obtainDataSource().getConnection()), true);
									}
									txObject.getConnectionHolder().setTransactionActive(true);
									con = txObject.getConnectionHolder().getConnection();
									con.setAutoCommit(false);
								}
								prepareSynchronization(status, definition);
							}
							
							
							
						}
					}
				}
				
				
				
				try {
     
					//火炬传递
					retVal = invocation.proceedWithInvocation();
				} catch (Throwable ex) {
     
					//事务回滚
					completeTransactionAfterThrowing(txInfo, ex);
					throw ex;
				}
				//事务的提交
				commitTransactionAfterReturning(txInfo);

			}
		}

你可能感兴趣的:(spring,spring,java,aop,spring事务,spring事务失效)