从 @Transactional 谈Spring AOP

本文探讨了Spring框架中@Transactional注解的使用,特别是在转账场景中的应用。在两个账户之间的转账过程中,@Transactional确保动作1(账户A减款)和动作2(账户B增款)作为不可分割的事务进行。当发生错误时,事务会回滚以保持数据一致性。在Spring Boot+jpa的示例中,TransactionInterceptor作为拦截器在方法外围管理事务,根据TransactionDefinition中的信息进行提交或回滚操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看@Transactional,这个annotation是用来捆绑事务的

场景

2个账户,A往B账户打100元,那么A账户减少100(动作1),同时B账户增加100(动作2).
这两个动作是不可拆分的,动作1完成后如果出了错,比如说B账户被冻结,那么这个时候应当进行将钱退回到A账户,这个行为叫回滚。

动作1,动作2相继完成后,就有了回执单,相当于这个事务完成了。

应用

以Spring Boot+jpa为例,看底层代码是如何实现的

  1. 引包:spring-boot-autoconfigure或者包含这个包的
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
<--包含这个包-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
 <--包含这个包-->
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

自动配置中有个配置事务的类 TransactionAutoConfiguration,可以看到jpa采用的是PlatformTransactionManager

@Configuration
@ConditionalOnClass({PlatformTransactionManager.class})
@AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
@EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
...
}

@AutoConfigureAfter 在加载配置的类之后再加载当前类
@ConditionalOnClass判断当前classpath下是否存在指定类,若是则将当前的配置装载入spring容器

这里加载的同包下的 JpaTransactionManager
JpaTransactionManager 通过继承 JpaTransactionManager 实现具体事务(获取底层transaction,进行数据库连接,提交回滚等操作)


那么,@Transactional是怎么启用的?
当然是通过拦截器org.springframework.transaction.interceptor.TransactionInterceptor
TransactionInterceptor 继承 MethodInterceptor 拦截方法,在方法的外围包一层事务

	@Override
	@Nullable
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

invokeWithinTransaction方法会将事务与当前线程绑定

  • 创建事务信息TransactionInfo(PlatformTransactionManager, TransactionAttribute, String joinpointIdentification),设置初始状态
    • TransactionDefinition 存放@Transactional中对应的信息
  • 若有异常调用completeTransactionAfterThrowing
  • 若没有 commitTransactionAfterReturning
  • 最后清除事务信息 cleanupTransactionInfo
	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());
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值