【Spring】声明式事务管理(一)

Spring 的声明式事务管理通过 @Transactional 注解让开发者无需手写事务控制逻辑,其底层由 Spring AOP 和 TransactionInterceptor 实现。本文将基于源码,简单说明事务异常回滚机制

在这里插入图片描述

【Spring】声明式事务管理(一)
【Spring】声明式事务管理(二)

一、Java 中实现事务的 3 种方式

方式场景关键 API / 注解
Jdbc 编程式单数据源,最底层Connection#setAutoCommit(false) / commit() / rollback()
Spring 编程式单数据源,模板化TransactionTemplate.execute(...)
Spring 声明式单/多数据源,日常首选@Transactional

二、Spring 声明式事务源码分析

1、开启Spring 声明式事务的总开关是 @EnableTransactionManagement

@Configuration
@EnableTransactionManagement        // ① 总开关
@ComponentScan
public class AppConfig {
    @Bean
    public PlatformTransactionManager txManager(DataSource ds) {
        return new DataSourceTransactionManager(ds);   // ② 具体策略
    }
}

@EnableTransactionManagement 通过 @Import(TransactionManagementConfigurationSelector.class) 将 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 注入容器

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
 /**
 * 1、导入 TransactionManagementConfigurationSelector 配置类
 */	
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default Integer.MAX_VALUE;
}


public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    public TransactionManagementConfigurationSelector() {
    }

    /**
    * 2、获取 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 全限定名
    */		
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[]{this.determineTransactionAspectClass()};
            default:
                return null;
        }
    }

    private String determineTransactionAspectClass() {
        return ClassUtils.isPresent("javax.transaction.Transactional", this.getClass().getClassLoader()) ? "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration" : "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";
    }
}

ProxyTransactionManagementConfiguration 声明了 3 个基础设施 Bean,这 3 个 Bean 分别负责组装 AOP、获取切入点、方法拦截器。核心的事务处理逻辑在 TransactionInterceptor 内

Bean 名称作用
BeanFactoryTransactionAttributeSourceAdvisorAdvisor(Pointcut + Advice)
AnnotationTransactionAttributeSource解析 @Transactional 的 Pointcut
TransactionInterceptor执行事务逻辑的 Advice
@Configuration(
    proxyBeanMethods = false
)
@Role(2)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    public ProxyTransactionManagementConfiguration() {
    }

    /**
    * 1、将事务的切入点和拦截器绑定在一起
    * 相当于于 @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
    *        + 
    * TransactionInterceptor 拦截
    */	
    @Bean(
        name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
    )
    @Role(2)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        advisor.setAdvice(transactionInterceptor);
        if (this.enableTx != null) {
            advisor.setOrder((Integer)this.enableTx.getNumber("order"));
        }

        return advisor;
    }

    /**
    * 2、事务的切入点
    */	
    @Bean
    @Role(2)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    /**
    * 3、事务拦截器,切入后执行的动作
    */	
    @Bean
    @Role(2)
    public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource);
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }

        return interceptor;
    }
}

TransactionInterceptor 在执行代理方法时,如果存在异常,就会调用事务管理器的 rollback 方法回滚

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

    @Nullable
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
		// 携带事务执行方法
        return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new TransactionAspectSupport.CoroutinesInvocationCallback() {
			...
        });
    }
	
	@Nullable
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
        TransactionAttributeSource tas = this.getTransactionAttributeSource();
        TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
		// 根据注解获取事务管理器
        TransactionManager tm = this.determineTransactionManager(txAttr);
		...
			Object retVal;
			try {
				// 执行代理方法
				retVal = invocation.proceedWithInvocation();
			} catch (Throwable var20) {
			    // 遇到异常触发回滚
				this.completeTransactionAfterThrowing(txInfo, var20);
				throw var20;
			} finally {
				this.cleanupTransactionInfo(txInfo);
			}
	}	

	
    protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
       ...
		// 调用事务管理器的回滚方法
       txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
       ...
    }	
}

DataSourceTransactionManager 是事务管理器实现类之一,它的回滚方法其实用的也是 con.rollback()

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {

	/**
	 *  rollback 调用 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);
		}
	}
}		


三、总结

Spring 声明式事务 = AOP 代理 + 模板方法
代理对象拦截 @Transactional 方法 → TransactionInterceptor 按固定 5 步(解析注解→创建/加入事务→执行业务→提交/回滚→清理) → 底层交给 PlatformTransactionManager(JDBC/JTA/Seata)真正做 commit/rollback。

四、学习交流

链接: Java-AI学习交流
一个人的精力是有限的,没有那么多的时间去探索新的事物,加入一个交流群就相当于增加了一个接触新事物、新想法、新机会的渠道,这就是交流群存在的意义,期待你的加入!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值