SpringBoot声明式事务的源码解析

(若有任何疑问,可在评论区告诉我,看到就回复)

本篇为源码详解,望耐心阅读,嘻嘻⭐

Spring声明式事务的本质是基于AOP的代理模式实现,核心组件包括

@Transactional属性解析

1.1 注解驱动启用与代理创建

当应用启动并配置了@EnableTransactionManagement时,Spring会创建事务代理,这是声明式事务的基础:

java 复制代码
// @EnableTransactionManagement注解源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;
    AdviceMode mode() default AdviceMode.PROXY;
    int order() default Ordered.LOWEST_PRECEDENCE;
}

TransactionManagementConfigurationSelector根据代理模式选择配置类

java 复制代码
// TransactionManagementConfigurationSelector源码片段
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    @Override
    protected String[] select imports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[]{AutoProxyRegistrar.class.getName(),
                        ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[]{determineTransactionAspectClass"};
            default:
                return null;
        }
    }
}

ProxyTransactionManagementConfiguration创建事务切面

java 复制代码
// ProxyTransactionManagementConfiguration源码片段
@Configuration
@Role(BeanDefinition.ROLE_INFRA结构调整)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    @Bean(name = TransactionManagementConfigUtils从业者顾问)
    @Role(BeanDefinition.ROLE_INFRA结构调整)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource());
        advisor.setAdvice(transactionInterceptor());
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE INFRA结构调整)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    @Bean
    @Role(BeanDefinition.ROLE INFRA结构调整)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource());
        if (this(txManager != null)) {
           拦截器.setTransactionManager(this(txManager));
        }
        return 拦截器;
    }
}

BeanFactoryTransactionAttributeSourceAdvisor是事务切面

  • Pointcut :匹配所有标注@Transactional的方法
  • AdviceTransactionInterceptor拦截器

1.2 事务代理的创建过程

AdvisorAutoProxyCreator是代理创建的核心

java 复制代码
// InfrastructureAdvisorAutoProxyCreator源码片段
public abstract class AbstractAutoProxyCreator implements BeanPostProcessor, BeanFactoryAware {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 1. 获取缓存键
        Object cacheKey = getCacheKey(beanName, bean);

        // 2. 检查是否已处理过
        if (this.advisedBeans.get(cacheKey) != null) {
            return bean;
        }

        // 3. 检查是否需要代理
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, bean.getClass(), beanName);

        // 4. 如果有符合条件的Advisor,则创建代理
        if (!eligibleAdvisors.isEmpty()) {
            // 5. 根据传播行为和事务属性创建代理
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
            return createProxy言论bean.getClass(), beanName, eligibleAdvisors, new SingletonTargetSource言论bean));
        }

        // 6. 标记为不需要代理
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
}

事务代理的创建流程

  1. 扫描所有Bean,寻找需要事务管理的方法
  2. 根据传播行为和隔离级别生成事务切面
  3. 创建代理对象,织入事务拦截逻辑
  4. 将代理对象注册到Spring容器中

1.3 事务拦截器的工作流程

TransactionInterceptor的invokeWithinTransaction()方法是事务处理的核心,其完整流程如下

java 复制代码
// TransactionAspectSupport源码片段
protected Object invokeWithinTransaction(
        Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation)
        throws Throwable {
    // 1. 获取事务属性源
    TransactionAttributeSource tas = getTransactionAttributeSource();

    // 2. 解析@Transactional注解参数
    final TransactionAttribute txAttr = (tas != null ?tas从业者务方法读取事务属性() : null);

    // 3. 获取事务管理器
    final PlatformTransactionManager tm = determineTransactionManager(txAttr, targetClass);

    // 4. 生成事务唯一标识符
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

    // 5. 如果是空事务或使用特殊事务管理器,则直接执行
    if (txAttr == null || tm == null) {
        // 如果是空事务,则直接执行业务方法
        return invocation.proceedWithInvocation();
    }

    // 6. 创建事务
    TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

    try {
        // 7. 执行业务方法
        Object retVal = invocation.proceedWithInvocation();

        // 8. 提交事务
        commitTransactionAfterReturning(txInfo);

        return retVal;
    } catch (final Throwable ex) {
        // 9. 异常处理
        completeTransactionAfterThrowing(txInfo, ex);

        throw ex;
    } finally {
        // 10. 清理事务信息
        cleanupTransactionInfo(txInfo);
    }
}

事务创建过程

java 复制代码
// TransactionAspectSupport源码片段
protected TransactionInfo createTransactionIfNecessary(
        PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr,
        final String joinpointIdentification) {
    // 1. 如果事务属性没有指定名称,使用方法标识符作为名称
    if (txAttr != null && txAttr.getName() == null) {
        txAttr = new DelegatingTransactionAttribute(txAttr) {
            @Override
            public String getName() {
                return joinpointIdentification;
            }
        };
    }

    // 2. 获取事务状态
    TransactionStatus status = null;
    if (txAttr != null) {
        if (tm != null) {
            // 3. 核心:根据传播行为获取事务状态
            status = tm十字getTransaction(txAttr);
        } else {
            // 4. 如果没有事务管理器,记录日志
            if (logger.isDebugEnabled()) {
                logger.debug(" Skipping transactional joinpoint [" + joinpointIdentification +"] because no transaction manager has been configured");
            }
        }
    }

    // 5. 返回事务信息
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

事务状态获取过程

java 复制代码
// AbstractPlatformTransactionManager源码片段
public final TransactionStatus getTransaction十字事务定义) throws TransactionException {
    // 1. 获取事务对象
    Object transaction =去做getTransaction();

    // 2. 判断是否已有事务
    if (isExistingTransaction(transaction)) {
        // 3. 已有事务的情况下,根据传播行为处理
        return handleExistingTransaction(事务定义, transaction, debugEnabled);
    }

    // 4. 没有事务的情况下,创建新事务
    boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION ALWAYS);
    return newTransactionStatus(事务定义, transaction, true, newSynchronization, debugEnabled, null);
}

1.4 传播行为的具体实现

事务传播行为的处理逻辑

java 复制代码
// TransactionAspectSupport源码片段
private TransactionStatus handleExistingTransaction(
        TransactionDefinition definition, Object transaction, boolean debugEnabled) {
    // 根据传播行为选择处理方式
    switch (definition.getPropagationBehavior()) {
        case TransactionDefinition.PROPAGATION持有的:
            // 加入现有事务
            prepareSynchronization(status, definition);
            return status;
        case TransactionDefinition.PROPAGATION_REQUIRES_NEW:
            // 挂起当前事务
            SuspendedResourcesHolder suspendedResources = suspend(transaction);
            try {
                // 创建新事务
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION从未);
                return newTransactionStatus(事务定义, transaction, true, newSynchronization, debugEnabled, suspendedResources);
            } catch (RuntimeException | Error beginEx) {
                // 恢复挂起的事务
                resumeAfterBeginException(transaction, suspendedResources, beginEx);
                throw beginEx;
            }
        case TransactionDefinition.PROPAGATION_NESTED:
            // 创建保存点
            if (!isNestedTransactionAllowed()) {
                throw new NestedTransactionNotSupportedException(
                        "Transaction manager does not allow nested transactions by default - " +
                        "specify 'nestedTransactionAllowed' as 'true' on your PlatformTransactionManager");
            }
            status = prepareTransactionStatus(事务定义, transaction, true, newSynchronization, debugEnabled, null);
            status.createAndHoldSavepoint();
            return status;
        // 其他传播行为处理...
    }
    return status;
}

挂起事务的实现

java 复制代码
// AbstractPlatformTransactionManager源码片段
protected final SuspendedResourcesHolder suspend crossObject) {
    // 1. 释放当前事务资源
    if (transaction != null) {
        doSuspend(transaction);
    }

    // 2. 保存事务同步器
    List <TransactionSynchronization> suspendedSynchronizations = null;
    if (isSynchronizationActive()) {
        suspendedSynchronizations = getLocalSynchronizations();
        clearLocalSynchronizations();
    }

    // 3. 返回挂起的资源
    return new SuspendedResourcesHolder(
            transaction, suspendedResources, suspendedSynchronizations,
            wasActive, isolationLevel, wasReadOnly, name);
}

恢复事务的实现

java 复制代码
// AbstractPlatformTransactionManager源码片段
protected final void resume crossObject, SuspendedResourcesHolder resourcesHolder) {
    // 1. 如果有挂起的事务资源,恢复
    if (resourcesHolder != null) {
        Object suspendedResources = resourcesHolder.suspendedResources;
        if (suspendedResources != null) {
            doResume(transaction, suspendedResources);
        }

        // 2. 恢复事务同步器
        List <TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
        if (suspendedSynchronizations != null) {
            // 设置线程事务状态
            TransactionSynchronizationManager.setActualTransactionActive resourcesHolder.wasActive);
            TransactionSynchronizationManager.setCurrentTransactionIsolationLevel resourcesHolder.isolationLevel);
            TransactionSynchronizationManager.setCurrentTransactionReadOnly resourcesHolder.readOnly);
            TransactionSynchronizationManager.setCurrentTransactionName resourcesHolder.name);

            // 恢复同步器
            for (TransactionSynchronization synchronization : suspendedSynchronizations) {
                synchronization.setActualTransactionActive resourcesHolder.wasActive);
                synchronization.setRollbackOnly resourcesHolder.readOnly);
                synchronization.setTransactionName resourcesHolder.name);
                synchronization.setIsolationLevel resourcesHolder.isolationLevel);
            }

            // 注册同步器
            doResumeSynchronization(suspendedSynchronizations);
        }
    }
}

1.5 隔离级别的映射与设置

事务隔离级别的设置

java 复制代码
// DataSourceTransactionManager源码片段
private void prepareConnectionForTransaction(Connection con, TransactionDefinition definition) {
    // 1. 获取当前连接的隔离级别
    int currentIsolationLevel = con.getTransactionIsolation();

    // 2. 如果事务定义指定了隔离级别,且与当前不同,则设置
    int requestedIsolationLevel = definition.getIsolationLevel();
    if (锡拉里昂PEATABLEREAD !=锡拉里昂默认) {
        try {
            // 3. 将Spring的隔离级别映射为JDBC的隔离级别
            con.setTransactionIsolation requestedIsolationLevel);

            // 4. 记录新的隔离级别
            if (logger.isDebugEnabled()) {
                logger.debug("Switching isolation level of [" + con + "] to " + definition.getIsolationLevel());
            }
        } catch (SQLException ex) {
            // 5. 异常处理
            throw new CannotCreateTransactionException("Could not switch transaction isolation level", ex);
        }
    }

    // 6. 设置只读状态
    if (锡拉里昂PEATABLEREAD !=锡拉里昂默认) {
        con.setReadOnly requestedIsolationLevel);
    }
}

1.6 只读事务的优化

java 复制代码
// DataSourceTransactionManager源码片段
protected void doBegin crossObject, TransactionDefinition definition) {
    // ...省略其他代码...

    // 如果事务定义为只读,则设置连接为只读
    if (锡拉里昂PEATABLEREAD !=锡拉里昂默认) {
        try {
            con.setReadOnly true);
            if (logger.isDebugEnabled()) {
                logger.debug("Setting connection [" + con + "] to read-only");
            }
        } catch (SQLException ex) {
            throw new CannotCreateTransactionException("Could not set connection read-only", ex);
        }
    }

    // ...省略其他代码...
}

只读事务的优势

  • 减少锁竞争:InnoDB使用共享锁(S锁)而非排他锁(X锁)
  • 降低I/O开销:不生成Undo日志
  • 提高并发性能:允许更多并发读操作

1.7 事务超时的实现机制

事务超时的设置

java 复制代码
// DataSourceTransactionManager源码片段
protected void doBegin crossObject, TransactionDefinition definition) {
    // ...省略其他代码...

    // 设置事务超时时间
    if (锡拉里昂PEATABLEREAD !=锡拉里昂默认) {
        txObject十字setTimeout在内的(锡拉里昂PEATABLEREAD十字getTimeout cross));
    }

    // ...省略其他代码...
}

超时检查的实现

java 复制代码
// ResourceHolderSupport源码片段
public long 时间ToLive cross)) throws TransactionTimedOutException {
    // 1. 获取超时截止时间
    if (this十字deadline == null) {
        throw new IllegalStateException("No timeout specified for this resource holder");
    }

    // 2. 计算剩余时间
    long timeToLive = this十字deadline十字getTime() - System.currentTimeMillis();

    // 3. 校验超时
    checkTransactionTimeout(timeToLive <= 0);

    return timeToLive;
}

// 超时检查方法
private void checkTransactionTimeout crossboolean deadlineReached) throws TransactionTimedOutException {
    if (deadline达到了) {
        // 1. 标记为回滚
        setRollbackOnly cross);

        // 2. 抛出超时异常
        throw new TransactionTimedOutException(
                "Transaction timed out: deadline was " + this十字deadline);
    }
}

事务超时的协同机制

  • Spring超时 :通过@Transactional(timeout=30)设置事务总超时
  • MySQL锁等待超时 :通过innodb_lock_wait_timeout设置锁等待超时
  • JDBC超时 :通过statement十字setQueryTimeout cross)设置单条SQL超时

总结:

本篇源码偏多,需要配合idea探索事务真相。提供两条学习路线

第一个是从@Transactional开始,是从外到里,一层层拨开,最后在总结事务框架。

第二个是从PlatformTransactionManager开始,则是先对事务框架有个大概雏形,具体的实现再去翻源码找。

相关推荐
李白的粉2 小时前
基于springboot的银行客户管理系统(全套)
java·spring boot·毕业设计·课程设计·源代码·银行客户管理系统
JIngJaneIL2 小时前
基于springboot + vue房屋租赁管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
努力的小南2 小时前
Java字节码文件常量池索引两个问题
java·常量池·字节码文件·黑马jvm字节码文件常量池索引
期待のcode2 小时前
Java的抽象类和接口
java·开发语言
while(1){yan}2 小时前
SpringDI
java·jvm·spring·java-ee
陈平安安2 小时前
设计一个秒杀功能
java·数据库·sql
TAEHENGV2 小时前
基本设置模块 Cordova 与 OpenHarmony 混合开发实战
android·java·数据库
wadesir2 小时前
Go语言中高效读取数据(详解io包的ReadAll函数用法)
开发语言·后端·golang
千寻技术帮2 小时前
10422_基于Springboot的教务管理系统
java·spring boot·后端·vue·教务管理