文章目录
前言
本章研究的源码基于 springboot 2.7.3
因为 spring 的事务是基于 aop 实现的,所以需要了解一下 aop 的基本原理, 可以参考另外一篇文章 aop原理解析
一、事务的自动配置
1.1 自动配置类的注入
事务是 springboot 本身自带的功能, 因此自动配置类在
org.springframework.boot.autoconfigure.AutoConfiguration.imports
这个文件中, spring将自己的自动配置类都放到了这一个文件中
spring.factories
在更高的版本中将被彻底废弃
1.2 TransactionAutoConfiguration
它负责注入一些支持事务的类,核心类为
JdkDynamicAutoProxyConfiguration
和CglibAutoProxyConfiguration
,这两个类上面都标注了EnableTransactionManagement
注解,这个注解引入了别的一些配置类
@AutoConfiguration(after = { JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
@ConditionalOnClass(PlatformTransactionManager.class)
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TransactionManagerCustomizers platformTransactionManagerCustomizers(
ObjectProvider<PlatformTransactionManagerCustomizer<?>> customizers) {
return new TransactionManagerCustomizers(customizers.orderedStream().collect(Collectors.toList()));
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(ReactiveTransactionManager.class)
public TransactionalOperator transactionalOperator(ReactiveTransactionManager transactionManager) {
return TransactionalOperator.create(transactionManager);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
public static class TransactionTemplateConfiguration {
@Bean
@ConditionalOnMissingBean(TransactionOperations.class)
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
return new TransactionTemplate(transactionManager);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
public static class JdkDynamicAutoProxyConfiguration {
}
/**
* 如果什么都没有配置的话会使用 Cglib 代理目标类
*/
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
}
1.3 @EnableTransactionManagement
引入了另外一个核心的配置了 TransactionManagementConfigurationSelector
// 引入了 TransactionManagementConfigurationSelector
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
// 简单记一下这个 AdviceMode = AdviceMode.PROXY
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
1.3 TransactionManagementConfigurationSelector
这个类是一个 ImportSelector,会将 selectImports 方法返回的全路径类名引入 spring,当前类又引入了一个
ProxyTransactionManagementConfiguration(重要)
和AutoProxyRegistrar(不重要)
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
// 这里是 PROXY, 因为这个是 EnableTransactionManagement 上配置的
switch (adviceMode) {
case PROXY:
// 引入核心类 ProxyTransactionManagementConfiguration
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
。。。
}
1.4 ProxyTransactionManagementConfiguration
这个类注入了 spring 事务实现的核心类
BeanFactoryTransactionAttributeSourceAdvisor
和TransactionInterceptor
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**
* 注入了一个 Advisor, Advisor 就是 spring 用来创建 aop 代理的
* Advisor 有一个 advice 属性, Advice 一般都继承了 MethodInterceptor(这个就是CGLIB的方法拦截器)
* 因此事务方法的执行必定会经过 TransactionInterceptor
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
/**
* 设置下面两个核心属性
*/
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
/**
* 引入了TransactionAttributeSource
* 这个类是用来创建代理对象的时候判断是否需要被 TransactionInterceptor 拦截的
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
/**
* 引入了拦截器 TransactionInterceptor
*/
@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;
}
}
二、@Transaction 注解的扫描(事务代理对象的创建)
这里直接跳过 spring 的生命周期流程,直接看事务代理对象的创建过程
aop原理篇说过,spring 的代理都是通过一个核心类AbstractAutoProxyCreator
的子类创建的,而这个类的注解实现类是AnnotationAwareAspectJAutoProxyCreator(是一个 SmartInstantiationAwareBeanPostProcessor)
,代理对象的创建在该类的postProcessAfterInitialization
方法中
2.1 代理对象创建核心方法 wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
// 获取能够拦截该 bean 的拦截器(Advisor)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
2.2 过滤出符合条件的 Advisor(getAdvicesAndAdvisorsForBean)
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取出所有的 Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 获取能够应用在该 bean 上的 Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
2.3 findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 调用 AopUtils.findAdvisorsThatCanApply
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
/**
* 循环判断每个 Advisor 是否能够应用到 clazz 上
*/
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// 该方法的终极判断交给了 canApply
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
2.4 AopUtils#canApply
看代码前要再次提醒, 事务的自动配置了注入的 Advisor 是
BeanFactoryTransactionAttributeSourceAdvisor
,这个 Advisor 是一个PointcutAdvisor
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
// 最终交给了 Pointcut 来判断,很合理,想想 Aop 不也是根据 pointcut 来判断的吗
// 注意:pca 是 BeanFactoryTransactionAttributeSourceAdvisor
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
/**
* 对于事务来讲 Advisor 是 BeanFactoryTransactionAttributeSourceAdvisor
* 那 pc 我们要去 BeanFactoryTransactionAttributeSourceAdvisor 这个类里面看一下
* 它其实是 BeanFactoryTransactionAttributeSourceAdvisor 的一个内部类(TransactionAttributeSourcePointcut)
*/
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// classFilter 是 TransactionAttributeSourceClassFilter
// 判断类上是否标注了 @Transaction 注解,其实这里基本上所有的都返回 true
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// 方法匹配,对于事务来讲就是判断方法上是否标注了 @Transaction 注解
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 判断方法上是否标注了 @Transaction 注解,如果标注了返回true
// 返回 true 就表示这个 Advisor 将拦截当前方法
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
2.5 TransactionAttributeSourcePointcut
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
// 设置过滤器 TransactionAttributeSourceClassFilter 是一个内部类,在下面
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
...
/**
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
/**
* {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}
* for filtering classes whose methods are not worth searching to begin with.
*/
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
// 最终会调用 TransactionAttributeSource#isCandidateClass
// 而在 ProxyTransactionManagementConfiguration 中已经注入了一个 TransactionAttributeSource
// 为 AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
2.6 AnnotationTransactionAttributeSource
/**
* 构造器
*/
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
if (jta12Present || ejb3Present) {
。。。
}
else {
// 保存了一个 SpringTransactionAnnotationParser
// SpringTransactionAnnotationParser 中就能看到 @Transaction 注解的扫描了
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
/**
* 判断是否符合条件
*/
@Override
public boolean isCandidateClass(Class<?> targetClass) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
}
2.7 SpringTransactionAnnotationParser
/**
* SpringTransactionAnnotationParser#isCandidateClass
* 判断类上是否有 @Transactional 注解
*/
@Override
public boolean isCandidateClass(Class<?> targetClass) {
return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}
三、事务处理的流程
核心类
TransactionInterceptor
,是事务方法的拦截器
3.1 TransactionInterceptor#invoke
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 调用 invokeWithinTransaction() 并且传入了一个 callback
return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
@Override
@Nullable
public Object proceedWithInvocation() throws Throwable {
// 调用目标方法
return invocation.proceed();
}
@Override
public Object getTarget() {
return invocation.getThis();
}
@Override
public Object[] getArguments() {
return invocation.getArguments();
}
});
}
3.2 invokeWithinTransaction
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 获取 @Transaction 注解上标注的属性
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);
// 这个 if 是适配 reactive,这里不管
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
。。。
}
// 事务管理器必须是一个 PlatformTransactionManager,否则抛出异常
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 目标方法的全路径名
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 (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 {
。。。
}
}
3.3 获取事务管理器 determineTransactionManager
@Nullable
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
// 如果 @Transaction 指定了事务管理器则使用指定的事务管理器
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return determineQualifiedTransactionManager(this.beanFactory, qualifier);
}
// 如果指定了事务管理器的名字
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
}
// 默认走下面这段逻辑
else {
TransactionManager defaultTransactionManager = getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
// 从 Spring 容器中获取 TransactionManager
// 默认获取到的是 JdbcTransactionManager 可以查看 4.1 章节
defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}
3.4 创建并开启事务 createTransactionIfNecessary
/**
* 创建事务如果需要的话
*/
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// 将 txAttr 包一层
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) {
// 从事务管理器中根据 @Transaction 上标注的属性获取事务
status = tm.getTransaction(txAttr);
}
。。。
}
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
/**
* tm.getTransaction()
*/
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// 如何 definition 为 null, 使用默认的
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 尝试获取已经存在的 transaction(DataSourceTransactionObject)
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 如果已经存在事务的话
if (isExistingTransaction(transaction)) {
// 事务的传播行为:当前已经在事务中了,如何处理当前事务
return handleExistingTransaction(def, transaction, debugEnabled);
}
// 判断事务超时
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 如果事务的传播行为为 MANDATORY(必须存在事务), 并且当前没有已经存在的事务, 抛出异常
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
/**
* NESTED:如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。
* 如果当前事务不存在,那么其行为与Required一样
*/
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 将当前事务的所有信息保存在 SuspendedResourcesHolder 中,也就是挂起
SuspendedResourcesHolder suspendedResources = suspend(null);
try {
// 开启事务
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
。。。
}
}
/**
* 开启事务
* 会创建数据库连接
* 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);
// 开启事务
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
/**
* doBegin
*/
@Override
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());
// 设置不自动提交
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);
}
// 绑定连接
if (txObject.isNewConnectionHolder()) {
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);
}
}
3.4 回滚操作
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);
}
/**
* txInfo.transactionAttribute.rollbackOn(ex)
* 这个方法判断遇到当前异常是否需要回滚
*/
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
。。。
}
else {
// 如果上面没有回滚, 则提交当前事务
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
。。。
}
}
}
/**
* RuleBasedTransactionAttribute#rollbackOn
*/
@Override
public boolean rollbackOn(Throwable ex) {
RollbackRuleAttribute winner = null;
int deepest = Integer.MAX_VALUE;
if (this.rollbackRules != null) {
// rollbackRules 就是我们在 @Transaction 配置的回滚的异常类
for (RollbackRuleAttribute rule : this.rollbackRules) {
int depth = rule.getDepth(ex);
// 判断是否匹配到了我们标注的异常
if (depth >= 0 && depth < deepest) {
deepest = depth;
winner = rule;
}
}
}
//如果没有匹配到我们配置的,或者我们没有配置,使用父类自带的回滚异常
// 父类:return (ex instanceof RuntimeException || ex instanceof Error);
// 有此可见,默认 spring 只会回滚 RuntimeException 和 Error
if (winner == null) {
return super.rollbackOn(ex);
}
return !(winner instanceof NoRollbackRuleAttribute);
}
3.5 提交事务
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());
}
}
/**
* AbstractPlatformTransactionManager#commit
*/
@Override
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");
}
// 由此可见我们其实可以在 spring 就算没有异常抛出的情况下依然回滚事务
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);
}
/**
* AbstractPlatformTransactionManager#processCommit
* 这个方法主要是处理提交前后的一些钩子方法
* cleanupAfterCompletion 这个方法比较重要,这个方法会恢复之前被挂起的事务数据
*/
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
// savepoint
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();
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");
}
}
。。。
try {
triggerAfterCommit(status);
}
finally {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
finally {
// 恢复事务数据 (TransactionSynchronizationManager) 里有几个 ThreadLocal
cleanupAfterCompletion(status);
}
}
3.6 事务的传播行为
3.6.0 前置知识
getTransaction 与 handleExistingTransaction
getTransaction 后半部分代码是当前没有事务的处理逻辑
handleExistingTransaction 是处理当前存在事务的逻辑
因此事务传播行为由这两部分组成
事务挂起
/**
* AbstractPlatformTransactionManager#suspend
* 返回了一个 SuspendedResourcesHolder
* SuspendedResourcesHolder 中保存了当前事务运行的一些数据,比如说数据库连接, 可以看 4.2 章节
* 这个会被保存在 DefaultTransactionStatus 中,后续事务提交之后会通过这个对象获取出来,然后在恢复
*/
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
Object suspendedResources = null;
if (transaction != null) {
suspendedResources = doSuspend(transaction);
}
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
}
catch (RuntimeException | Error ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
}
else if (transaction != null) {
// Transaction active but no synchronization active.
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
else {
// Neither transaction nor synchronization active.
return null;
}
}
事务恢复
事务恢复操作一般在新的事务提交了之后
/**
* AbstractPlatformTransactionManager#resume
*/
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
doResume(transaction, suspendedResources);
}
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
if (suspendedSynchronizations != null) {
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
doResumeSynchronization(suspendedSynchronizations);
}
}
}
3.6.1 Propagation.REQUIRED
有事务就加入事务,没有事务就创建一个事务,默认值
/**
* AbstractPlatformTransactionManager#getTransaction
* 这个方法后面是处理当前没有事务的逻辑
*/
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 挂起了 null
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
// 新创建一个事务
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
3.6.2 Propagation.REQUIRES_NEW
每次都新建一个事务
/**
* AbstractPlatformTransactionManager#handleExistingTransaction
*/
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 {
// startTransaction 会创建一个新的事务(回创建新的数据库连接)
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
3.6.3 Propagation.SUPPORTS
当前有事务就加入事务, 没有事务就当作非事务运行
springboot 源码中并没有对 SUPPORTS 的直接判断,而是走了 else 逻辑
3.6.4 Propagation.MANDATORY
如果不存在事务就抛出异常
/**
* AbstractPlatformTransactionManager#getTransaction
*/
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
3.6.5 Propagation.NOT_SUPPORTED
以非事务运行, 如果存在事务,将当前事务挂起
/**
* AbstractPlatformTransactionManager#handleExistingTransaction
*/
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);
}
3.6.6 Propagation.NEVER
如果存在事务就抛出异常
/**
* AbstractPlatformTransactionManager#handleExistingTransaction
*/
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
3.6.7 Propagation.NESTED
如果存在外部事务则创建事务来作为当前事务的嵌套事务,如果没有外部事务,则等价于Propagation.REQUIRED
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.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// 创建一个新的事务,注意:并没有挂起原来的事务,因此是嵌套事务
return startTransaction(definition, transaction, debugEnabled, null);
}
}
四、其他源码
4.1 事务管理器的注入
4.1.1 事务管理器自动配置类
4.1.2 DataSourceTransactionManagerAutoConfiguration
/**
* 事务管理器的自动配置类
*/
@AutoConfiguration
@ConditionalOnClass({ JdbcTemplate.class, TransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(DataSource.class)
static class JdbcTransactionManagerConfiguration {
/**
* 注入事务管理器
*/
@Bean
@ConditionalOnMissingBean(TransactionManager.class)
DataSourceTransactionManager transactionManager(Environment environment, DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
// 创建事务管理器
DataSourceTransactionManager transactionManager = createTransactionManager(environment, dataSource);
// 可以对事务管理器进行自定义处理
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
return transactionManager;
}
/**
* 创建事务管理器
*/
private DataSourceTransactionManager createTransactionManager(Environment environment, DataSource dataSource) {
/**
* 从 environment 中获取这个属性
* 如果是 true 返回 JdbcTransactionManager, false 返回 DataSourceTransactionManager
* 默认是 true, 也就是默认的 TransactionManager 是 JdbcTransactionManager
*/
return environment.getProperty("spring.dao.exceptiontranslation.enabled", Boolean.class, Boolean.TRUE) ? new JdbcTransactionManager(dataSource) : new DataSourceTransactionManager(dataSource);
}
}
}
4.2 TransactionSynchronizationManager
public abstract class TransactionSynchronizationManager {
// resources 中存放的是 ConnectionHolder,可以简单理解为数据库连接对象
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
// 当前事务名称: 一般是方法的全路径名
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<>("Current transaction name");
// 当前事务是否只读
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<>("Current transaction read-only status");
// 当前事务隔离级别
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<>("Current transaction isolation level");
//
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
}
五、事务使用的注意事项
5.1 事务失效场景
spring 事务实现的本质是基于代理,抛出异常之后代理对象捕获到异常才会回滚, 因此事务失效总而言之可分为
- 没有创建出正确的代理对象
- 抛出的异常未被代理对象捕获到,默认 spring 只会回滚
RuntimeException
和Error
,除了这些异常别的异常需要手动指定