Spring事务注解@Transactional的实现原理
@Transactional 注解元数据驱动的声明式事务
基本原理是:
将对应的方法通过注解元数据,标注在业务方法或者所在的对象上,然后在业务执行期间,通过AOP拦截器反射读取元数据信息,最终将根据读取的业务信息构建事务管理支持。
不同的方法之间的事务传播保证在同一个事务内,是通过统一的数据源来实现的,事务开始时将数据源绑定到ThreadLocal中,后续加入的事务从ThreadLocal获取数据源来保证数据源的统一。
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional { @AliasFor("transactionManager") String value() default ""; //事务管理器名称 @AliasFor("value") String transactionManager() default ""; //事务传播模式 Propagation propagation() default Propagation.REQUIRED; //事务隔离级别 Isolation isolation() default Isolation.DEFAULT; //超时时间 int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; //是否是只读事务 boolean readOnly() default false; //需要回滚的异常类 Class<? extends Throwable>[] rollbackFor() default {}; //需要回滚的异常类名称 String[] rollbackForClassName() default {}; //排除回滚的异常类 Class<? extends Throwable>[] noRollbackFor() default {}; //排除回滚的异常类名称 String[] noRollbackForClassName() default {}; }
这里通过SpringBoot代码来分析实现过程,源码中删除了部分代码,只保留了一些重要部分
// 事务自动配置类 注意类里面使用的@EnableTransactionManagement注解 org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration public class TransactionAutoConfiguration { @Configuration @ConditionalOnBean(PlatformTransactionManager.class) @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class) public static class EnableTransactionManagementConfiguration { //注意这里使用的@EnableTransactionManagement注解 @Configuration @EnableTransactionManagement(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) public static class JdkDynamicAutoProxyConfiguration { } //注意这里使用的@EnableTransactionManagement注解 @Configuration @EnableTransactionManagement(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { } } }
这里只分析proxy模式
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) 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_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } //这里注入了TransactionInterceptor拦截器bean~~~~ @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
TransactionInterceptor拦截器通过元数据获取事务定义信息TransactionDefinition,根据Definition信息获取PlatformTransactionManager(TM),tm接口抽象了事务的实现流程,默认的tm是DataSourceTransactionManager(通过DataSourceTransactionManagerAutoConfiguration初始化的),tm中的getTransaction根据事务的传播方式,开启、加入、挂起事务。
@Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); if (definition == null) { // 使用默认的Definition definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) { //已经存在事务,进入单独的方法处理 return handleExistingTransaction(definition, transaction, debugEnabled); } // 检查timeout参数 if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // 当前必须存在事务,否则抛出异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { //获取当前的一些事务信息,用于当前事务执行完后恢复 SuspendedResourcesHolder suspendedResources = suspend(null); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //构造一个新事务的TransactionStatus(包含嵌套事务SavePoint的支持) DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //开启新的事务 doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error ex) { //异常,恢复挂起的事务信息 resume(null, suspendedResources); throw ex; } } else { //空的事务 boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
来看一个简单实现版
1. 自定义注解 @MyTransaction
/** * @author yangxj * @see org.springframework.transaction.annotation.SpringTransactionAnnotationParser * @see org.springframework.transaction.interceptor.TransactionAttribute * @see org.springframework.transaction.TransactionDefinition */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyTransaction { String value() default ""; }
2. 自定义通知Advice
/** * @author yangxj * * @see org.springframework.transaction.PlatformTransactionManager * @see org.springframework.jdbc.datasource.DataSourceTransactionManager * @see org.springframework.transaction.interceptor.TransactionInterceptor */ @Slf4j public class MyTransactionInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { log.info("拦截到事务方法:{}", methodInvocation.getMethod().getName()); try { return methodInvocation.proceed(); // commit 提交事务 } catch (Exception e) { // rollback 回滚事务 } return null; } }
3. 织入
/** * @author yangxj * @see org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration * @see org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor */ @Configuration public class CommonConfiguration { @Bean public DefaultPointcutAdvisor myTransactionPointcutAdvisor() { DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(); // 切面 Aspect advisor.setPointcut(new AnnotationMatchingPointcut(null, MyTransaction.class)); // 方法级别注解匹配 切入点 pointcut advisor.setAdvice(new MyTransactionInterceptor()); // 通知 advice return advisor; } }
4. 演示
参考文章:
https://segmentfault.com/a/1190000022790265
https://www.cnblogs.com/yangxijun/p/14844490.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架