springboot @Transactional事务原理源码

文章详细阐述了SpringBoot中事务管理的实现过程,包括注册事务管理器、事务增强器、事务注解解析和代理对象的生成。重点介绍了BeanFactoryTransactionAttributeSourceAdvisor、TransactionInterceptor的角色以及如何通过AnnotationAwareAspectJAutoProxyCreator处理事务注解并生成动态代理。

springboot事务必要组件和过程:

1.注册事务管理器DatasouceTransactionManager

2.注册事务增强器BeanFactoryTransactionAttributeSourceAdvisor,里面包含事务拦截器TransactionInterceptor

3.注册事务注解解析用的后置处理器AnnotationAwareAspectJAutoProxyCreator,里面用来生成代理对象

4.通过代理对象调用方法,会先走代理对象的invoke()方法,通过事务拦截器来开启事务,执行目标方法,提交或回滚事务

一、注入BeanFactoryTransactionAttributeSourceAdvisor和TransactionInterceptor和DatasouceTransactionManager

1.注册DatasouceTransactionManager

通过springboot的spi机制,在DataSourceTransactionManagerAutoConfiguration中的DataSourceTransactionManagerConfiguration中,通过@Bean的方式注入了DataSourceTransactionManager到spring容器

2.注入BeanFactoryTransactionAttributeSourceAdvisor和TransactionInterceptor

扫描spring-boot-autoconfigure依赖包下的META-INF/spring.factories,加载文件里的TransactionAutoConfiguration类,可以看到sringboot在2.0之后默认使用了cglib代理,下面将的是jdk的代理,原理是一样的

解析TransactionAutoConfiguration类里的@EnableTransactionManagement注解,根据该注解上的@Import加载TransactionManagementConfigurationSelector类

通过TransactionManagementConfigurationSelector类的selectImports方法加载ProxyTransactionManagementConfiguration类

ProxyTransactionManagementConfiguration类通过@Bean加载BeanFactoryTransactionAttributeSourceAdvisor类,该类实现了Pointcut,并且在该类里注入了实现了Advise接口的TransactionInterceptor类,TransactionInterceptor就是事务拦截器。

这里setTransactionManager其实是一个null,后面拿事务管理器时是从单例池中拿,不是用的这个。

另外要提一点的是很多类中之所以可以用到BeanFactory(DefaultListableBeanFactory),是因为实现了BeanFactoryAware,spring在初始化bean的时候会将beanFactory设置进去

二、注入AnnotationAwareAspectJAutoProxyCreator切面解析处理器

通过spi机制自动装载AopAutoConfiguration类,加载AopAutoConfiguration类,根据proxyTargetClass配置来选择是使用jdk的proxy还是cglib来生成动态代理类,截图如下:

解析@EnableAspectJAutoProxy注解,通过该注解上的@Import加载AspectJAutoProxyRegistrar类

AspectJAutoProxyRegistrar类会向Spring容器注册AnnotationAwareAspectJAutoProxyCreator类,该类实现了BeanPostProcessor接口,所以这个aop逻辑是在Springbean生成过程中通过后置处理器逻辑来实现的。

AnnotationAwareAspectJAutoProxyCreator继承AspectJAwareAdvisorAutoProxyCreator继承AbstractAdvisorAutoProxyCreator继承AbstractAutoProxyCreator实现BeanFactoryAware,

因为AnnotationAwareAspectJAutoProxyCreator最顶层实现了BeanFactoryAware所以初始化时需要调用AbstractAdvisorAutoProxyCreator的setBeanFactory方法,就会走下图的逻辑,就会走this.initBeanFactory逻辑,

其实就是调用了子类AnnotationAwareAspectJAutoProxyCreator的initBeanFactory方法,然后调用super.initBeanFactory方法

也就是调用了AbstractAdvisorAutoProxyCreator的initBeanFactory方法,这个方法里面初始化了this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);

后面会有一句代码叫this.advisorRetrievalHelper.findAdvisorBeans()。所以要知道this.advisorRetrievalHelper就是在这里初始化的

三、事务注解解析和代理生成过程

前面的步骤暂时省略了,这里只分析从开始走后置处理器的逻辑

AnnotationAwareAspectJAutoProxyCreator

执行AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator的postProcessAfterInitialzation方法

this.wrapIfNecessary()方法就是要进行生成代理了

this.getAdvicesAndVisorsForBean调用的是AbstractAutoProxyCreator子类AbstractAdvisorAutoProxyCreator中的

ProxyTransactionManagementConfiguration中通过@Bean注册的BeanFactoryTransactionAttributeSourceAdvisor名称就叫做"org.springframework.transaction.config.internalTransactionAdvisor",所以下面传入一个DefaultListableBeanFactory和Avisor.class,从spring容器中查找Avisor类型的bean,然后获取它们的名称,advisorNames就包含了"org.springframework.transaction.config.internalTransactionAdvisor",下面就通过name和Advisor.class获取对应的BeanFactoryTransactionAttributeSourceAdvisor事务增强器

那么candidateAdvisors中包含从spring容器中获取出来的所有增强器,candidateAdvisors之所以是一个集合,是因为容器中是Advisor.class类型的bean可能不止是BeanFactoryTransactionAttributeSourceAdvisor,下图中就是还有一个Druid连接池sql监控的增强器

然后通过传入目标beanName和beanClass筛选出属于本类需要的增强器,如果你的类或者方法上有@Transactional注解,那么返回的eligibleAdvisors中就有BeanFactoryTransactionAttributeSourceAdvisor,

AopUtils#canApply(Pointcut, Class , boolean) 方法中会调用到 TransactionAttributeSourcePointcut#matches 方法

BeanFactoryTransactionAttributeSourceAdvisor继承了PoincutAdvisor

canApply中会调用BeanFactoryTransactionAttributeSourceAdvisor.getPointCut()返回一个TransactionAttributeSourcePointcut

然后pointcut再调用getMethodMatcher()返回一个MethodMatcher也就是TransactionAttributeSourcePointcut自己,因为getMethodMatcher()是在父类StaticMethodMatcherPointcut中调用的,而父类StaticMethodMatcherPointcut继承了StaticMethodMatcher继承了MethodMatcher,所以TransactionAttributeSourcePointcut也是一个MethodMatcher。

TransactionAttributeSourcePointcut#getTransactionAttributeSource 返回的是:AnnotationTransactionAttributeSource 实例,AnnotationTransactionAttributeSource继承自:AbstractFallbackTransactionAttributeSource, 故此TransactionAttributeSourcePointcut#matches 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法

SringTransactionAnnotationParser实在下图中被创建的

以上是this.getAdvicesAndAdvisorForBean方法内部调用过程,调用完该方法出来后,回到下图中创建代理对象this.createProxy

Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);返回指定的拦截器

this.createAopProxy就是创建一个JdkDynamicAopProxy代理对象(jdk代理为例子),JdkDynamicAopProxy继承了InvocationHandler

那么将来通过controller调用某个service的某个加了@Transactional的方法,就会首先进入invoke方法进行拦截

invoke方法中会执行下面一段,chain就是根据method把所需要的拦截器拿出来,因为拦截器已经在之前的操作this.createAopProxy中设置进了成员属性advised,所以这里可以通过this.advised.getInterceptorsAndDynamicInterceptionAdvice拿出来,例如method加了@Transactional,那么chain中就会包含BeanFactoryTransactionAttributeSourceAdvisor#TransactionInterceptor。如果说chain是空的,那么就会直接通过反射调用原始bean的方法,那就没有事务。

下面调用的就是拦截器的invoke方法

那么其中的一个拦截器TransactionInterceptor的invoke方法就会被调用,就是开启事务的逻辑了,逻辑如下

<think> 我们正在寻找在Spring Boot中使用`@Transactional`注解时事务执行的源码入口。具体地,用户使用了`@Transactional(rollbackFor = Exception.class, timeout = Constants.DEFAULT_TX_TIMEOUT)`这样的注解。我们的目标是找到事务执行的入口点。 在Spring中,事务管理是通过AOP(面向切面编程)来实现的。具体来说,Spring使用`TransactionInterceptor`来拦截带有`@Transactional`注解的方法,并在方法执行前后管理事务。 ### 事务执行流程简要概述 1. **代理创建**:当Spring容器启动时,对于带有`@Transactional`注解的Bean,Spring会创建代理对象(JDK动态代理或CGLIB代理)。 2. **方法拦截**:当调用代理对象的方法时,会先经过`TransactionInterceptor`的`invoke()`方法。 3. **事务处理**:在`TransactionInterceptor`内部,会调用父类`TransactionAspectSupport`的`invokeWithinTransaction()`方法,该方法负责整个事务的逻辑。 ### 源码入口:`TransactionInterceptor` `TransactionInterceptor`是Spring事务拦截器,它实现了`MethodInterceptor`接口,因此其`invoke()`方法是事务执行的入口点。 #### 关键代码片段分析 在`TransactionInterceptor`中,事务执行的核心逻辑在父类`TransactionAspectSupport`的`invokeWithinTransaction`方法中。以下是简化后的调用链: 1. `TransactionInterceptor.invoke()` 2. `TransactionAspectSupport.invokeWithinTransaction()` 在`invokeWithinTransaction`方法中,主要步骤包括: - 获取事务属性(包括超时时间、回滚规则等) - 创建事务(如果必要) - 执行被代理的业务方法 - 根据执行情况提交或回滚事务 ### 具体源码追踪 #### 1. `TransactionInterceptor.invoke()` ```java public Object invoke(MethodInvocation invocation) throws Throwable { // 调用父类方法 return invokeWithinTransaction(invocation.getMethod(), invocation.getThis().getClass(), new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { return invocation.proceed(); } }); } ``` #### 2. `TransactionAspectSupport.invokeWithinTransaction()` ```java protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // 获取事务属性(包括超时时间、回滚规则等) final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass); // 处理声明式事务 if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // 创建事务 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // 执行被代理的业务方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // 异常处理:回滚或提交 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } // 提交事务 commitTransactionAfterReturning(txInfo); return retVal; } else { // 编程式事务处理(略) } } ``` ### 关键点:超时和回滚规则的设置 - **超时设置**:在创建事务时,`createTransactionIfNecessary`方法内部会调用`tm.getTransaction(txAttr)`来获取事务状态。此时,事务管理器(如`DataSourceTransactionManager`)会根据`@Transactional`注解中的`timeout`属性(通过`txAttr`传递)来设置事务超时时间。 - **回滚规则**:在`completeTransactionAfterThrowing`方法中,会根据异常类型和`@Transactional`中`rollbackFor`设置的规则来决定是否回滚[^3][^4]。 ### 总结 1. **入口方法**:事务执行的入口是`TransactionInterceptor.invoke()`,它进一步调用`TransactionAspectSupport.invokeWithinTransaction()`。 2. **超时生效点**:在创建事务时(`createTransactionIfNecessary`方法内部),事务管理器会根据注解中的`timeout`值设置超时。 3. **回滚规则生效点**:在异常处理阶段(`completeTransactionAfterThrowing`方法中),会检查异常是否符合回滚规则[^3][^4]。 因此,对于用户的问题,事务执行的源码入口是`TransactionInterceptor.invoke()`方法,而具体的超时和回滚规则处理则分别发生在事务创建和异常处理阶段。 §§相关问题§§ 1. Spring事务管理器中超时时间是如何传递给底层数据库的? 2. 在分布式事务场景下,`@Transactional`的超时设置如何生效? 3. Spring如何处理嵌套事务的超时和回滚规则? </think> ### Spring Boot 中 `@Transactional` 事务源码执行入口分析 在 Spring Boot 中使用 `@Transactional(rollbackFor = Exception.class, timeout = Constants.DEFAULT_TX_TIMEOUT)` 注解时,事务处理的源码执行入口是 **`TransactionInterceptor.invoke()`** 方法,其核心调用链路如下: #### 1. **事务拦截器入口:`TransactionInterceptor.invoke()`** ```java public Object invoke(MethodInvocation invocation) throws Throwable { // 获取目标类和方法 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // 调用事务处理核心方法 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); } ``` 此方法是事务执行的**第一入口点**,负责拦截所有 `@Transactional` 注解的方法调用[^3]。 #### 2. **事务处理核心:`TransactionAspectSupport.invokeWithinTransaction()`** ```java protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // 获取事务属性(含timeout和rollbackFor设置) TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); // 确定事务管理器 PlatformTransactionManager tm = determineTransactionManager(txAttr); // 创建事务(关键步骤) TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); try { // 执行业务方法 Object retVal = invocation.proceedWithInvocation(); // 提交事务 commitTransactionAfterReturning(txInfo); return retVal; } catch (Throwable ex) { // 异常回滚处理(应用rollbackFor规则) completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } } ``` 此方法完成三个核心操作[^3][^4]: 1. **解析注解属性**:提取 `timeout` 和 `rollbackFor` 配置 2. **创建事务**:在 `createTransactionIfNecessary()` 中应用超时设置 3. **异常处理**:在 `completeTransactionAfterThrowing()` 应用回滚规则 #### 3. **超时设置生效点:`AbstractPlatformTransactionManager.getTransaction()`** ```java public final TransactionStatus getTransaction( @Nullable TransactionDefinition definition) { // 创建事务状态对象 DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debug, suspendedResources); // 应用超时设置(关键步骤) int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { status.setTimeoutInSeconds(timeout); } // 开启JDBC事务 doBegin(transaction, definition); return status; } ``` 在此方法中: 1. 通过 `determineTimeout()` 解析注解中的 `timeout` 值 2. 通过 `status.setTimeoutInSeconds()` 设置事务超时 3. 最终在 `doBegin()` 中将超时值传递给 JDBC 连接[^1][^3] #### 4. **回滚规则执行点:`RuleBasedTransactionAttribute.rollbackOn()`** ```java public boolean rollbackOn(Throwable ex) { // 遍历rollbackFor配置的异常类型 for (RollbackRuleAttribute rule : this.rollbackRules) { if (rule.getDepth(ex) >= 0) { return true; // 匹配则回滚 } } return false; // 否则不回滚 } ``` 此方法在 `completeTransactionAfterThrowing()` 中被调用,根据 `rollbackFor` 配置决定是否回滚[^2][^4]。 ### 执行流程图解 ```mermaid graph TD A[调用@Transactional方法] --> B(TransactionInterceptor.invoke) B --> C(TransactionAspectSupport.invokeWithinTransaction) C --> D[解析timeout/rollbackFor] C --> E[创建事务 applyTimeout] C --> F[执行业务方法] F --> G{是否异常?} G -- 是 --> H[apply rollbackFor规则] G -- 否 --> I[提交事务] H --> J[回滚事务] ``` ### 关键结论 1. **主入口**:`TransactionInterceptor.invoke()` 是事务执行的起点 2. **超时应用点**:在 `AbstractPlatformTransactionManager.getTransaction()` 中设置超时值 3. **回滚决策点**:`RuleBasedTransactionAttribute.rollbackOn()` 实现 `rollbackFor` 规则 4. **最终执行**:通过 `DataSourceTransactionManager` 将设置传递给底层 JDBC 连接[^1][^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值