本文编写于 957 天前,最后修改于 952 天前,其中某些信息可能已经过时。
@Transactional注解的运行原理
- 首先生成事务类的动态代理对象,在执行动态代理事务类的事务方法时,会执行事务拦截器
TransactionInterceptor
; 接着事务核心组件
TransactionAspectSupport
开始执行事务方法主流程;- 首先调用
Connection.setAutoCommit(false)
方法开启事务,本质是基于jdbc连接开启事务方法; - 接着调用目标方法
invocation.proceedWithInvocation()
,依旧采用ReflectiveMethodInvocation
方法调用组件调用目标方法; - 在目标方法执行完成后,判断目标方法是否发生异常;
- 如果发生异常,就调用
Connection.rollback()
方法回滚事务,本质是基于jdbc连接回滚事务; - 如果没有发生异常,就调用
Connection.commit()
方法提交事务,本质是基于jdbc连接提交事务;
- 首先调用
@Transactional事务动态代理对象创建过程
该创建过程和AOP的创建过程一致,只不过事务使用的是BeanFactoryTransactionAttributeSourceAdvisor
事务增强advisor
来处理事务代理对象;
- 从IOC容器中获取bean;
- 调用bean后置处理器
AbstractAutoProxyCreator
的postProcessBeforeInstantiation()
方法; - 判断是否指定
targetSource
,如果指定了targetSource
会跳过bean的实例化和初始化流程,也就是会直接创建AOP代理; - 如果没有指定
targetSource
,执行正常创建bean的流程,执行bean的初始化,执行initMethod方法; - 调用bean后置处理器
AbstractAutoProxyCreator
的postProcessAfterInitialization()
方法; - 执行
wrapIfNecessary
方法包装需要被代理的bean; 获取所有的增强
advisors
;- 获取xml方式配置的增强
advisors
; - 此处会获取到
BeanFactoryTransactionAttributeSourceAdvisor
事务增强advisor
; - 获取
@Aspect
注解配置的增强advisors
,调用BeanFactoryAspectJAdvisorsBuilder
的buildAspectJAdvisors
方法; - 获取IOC容器中的所有bean,判断是否添加
@Aspect
注解; - 通过
@Aspect
注解配置的增强advisors
和事务增强的advisor
合并在一起将所有的advisors
返回;
- 获取xml方式配置的增强
- 调用
findAdvisorsThatCanApply
方法,从所有增强的advisor
中找到与当前bean相匹配的增强Advisors
; 遍历当前bean中所有方法依次与
advisor
的切点表达式进行匹配;- 判断目标类不是java自带的类并且不是Orderd接口类型,如果不满足该条件就不处理当前bean;
- 如果满足上面的条件,就获取
@Transactional
注解中配置的属性(AbstractFallbackTransactionAttributeSource#getTransactionAttribute
); - 判断目标方法是否是public方法,如果不是,则不处理当前方法;
- 判断目标方法上是否可以获取到
@Transactional
事务属性,如果可以获取到,就将BeanFactoryTransactionAttributeSourceAdvisor
事务增强advisor
添加到当前方法的advisors
中; - 如果未从方法上获取事务属性,就尝试从类上获取
@Transactional
事务属性,如果可以获取到,就将BeanFactoryTransactionAttributeSourceAdvisor
事务增强advisor
添加到当前方法的advisors
中;
- 创建
ProxyFactory
对象,并设置相关属性; - 调用
createAopProxy
方法,获取构造方法默认创建的DefaultAopProxyFactory
代理工厂对象,开始选择代理方式并创建代理对象;
详细创建流程可以参考Spring AOP 动态代理的创建过程
@Transactional事务动态代理对象执行过程
- 调用事务代理对象的事务方法;
调用
AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
方法获取拦截器链chain
;- 从
methodCache
缓存中查找是否存在目标方法对应的拦截器链; - 如果没有从
methodCache
缓存中找到对应的拦截器链,从ProxyFactory
中获取目标类对应的类级别增强advisors
; 依次遍历所有的增强
advsiors
是否与目标方法匹配,该过程与@Transactional
事务代理对象创建过程中的匹配类似;- 判断目标类不是java自带的类并且不是Orderd接口类型,如果不满足该条件就不处理当前bean;
- 如果满足上面的条件,就获取
@Transactional
注解中配置的属性(AbstractFallbackTransactionAttributeSource#getTransactionAttribute
); - 判断目标方法是否是public方法,如果不是,则不处理当前方法;
- 判断目标方法上是否可以获取到
@Transactional
事务属性,如果可以获取到,就获取BeanFactoryTransactionAttributeSourceAdvisor
事务增强advisor
中的拦截器; - 如果未从方法上获取事务属性,就尝试从类上获取
@Transactional
事务属性,如果可以获取到,就获取BeanFactoryTransactionAttributeSourceAdvisor
事务增强advisor
中的拦截器; - 调用
AbstractBeanFactoryPointcutAdvisor#getAdvice
方法获取增强Advice
,该方法会最终调用beanFactory.getBean(this.adviceBeanName, Advice.class)
来获取拦截器TransactionInterceptor
; - 最终将匹配的
Advisor
收集到interceptorList
,并放到methodCache
缓存中,以便下一次从缓存获取;
- 从
- 如果拦截器链
chain
为空,则通过反射调用目标方法,将结果返回; - 如果拦截器链
chain
不为空,就将拦截器链chain
统一封装为MethodInvocation
; 调用
ReflectiveMethodInvocation#proceed
,执行拦截器链;执行拦截器
TransactionInterceptor#invoke
方法;- 开启事务;
- 执行目标方法;
- 判断执行目标方法后是否发生异常,如果发生异常,就回滚事务,并抛出该异常;
- 如果没有发生异常,就提交事务;
- 返回执行结果。
事务失效的常见场景
- 事务对象没有被Spring管理;
- 事务方法不是public修饰;
- 方法内部调用事务方法,这里直接内部调用,没有经过动态代理对象的增强处理,事务增强处理无法执行;
- 异常在方法内部捕获,且没有抛出;
- rollbackFor属性配置错误;
- 数据库引擎不支持事务。