Spring 事务管理 @Transactional 注解 , TransactionInterceptor 原理深度剖析

Spring事务管理 @Transactional 注解管理事务原理深度剖析

一、 @Transactional 注解解析

方法入口:SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)
SpringTransactionAnnotationParser#parseTransactionAnnotation

下面看 parseTransactionAnnotation方法做了什么 :
parseTransactionAnnotation方法详细

parseTransactionAnnotation 方法的作用是将注解中声明的属性都解析加入到 RuleBasedTransactionAttribute 中
并return 给调用者.

二、为什么是SpringTransactionAnnotationParser 解析Transactional注解 , 从哪里来的?

查看 SpringTransactionAnnotationParser 的引用 , 只有 AnnotationTransactionAttributeSource 的构造方法中有
SpringTransactionAnnotationParser  从哪里来

三、那么为什么是 AnnotationTransactionAttributeSource ?

这我们就不得不从 <tx:annotation-driven transaction-manager=“transactionManager”/> 讲起了(spring 是如何处理各种xml标签的,由谁解析, 这里不再赘述)

看 TxNamespaceHandlerTxNamespaceHandler.init

然后到 AnnotationDrivenBeanDefinitionParser , 看AnnotationDrivenBeanDefinitionParser.parse方法
AnnotationDrivenBeanDefinitionParser.parse

3.1 看 AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext) 方法做了什么:

①  AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); 

:
注册或更新 AutoProxyCreator 定义 beanName 为 org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
如果internalAutoProxyCreator的BeanDefinition已经存在,则根据优先级更新BeanDefinition
在这里我们注册的是AnnotationAwareAspectJAutoProxyCreator

那么为什么要注册AnnotationAwareAspectJAutoProxyCreator 呢?

其实,实现AOP处理是其实是通过BeanPostProcessor机制实现的。AnnotationAwareAspectJAutoProxyCreator的父类实现BeanPostProcessor类型的接口,而生成代理的逻辑就在AnnotationAwareAspectJAutoProxyCreator的BeanPostProcessor接口实现postProcessAfterInitialization 方法里。这里的逻辑在后面介绍。

3.2 接着看 AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext) 方法做了什么:

String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName))

TRANSACTION_ADVISOR_BEAN_NAME的值为org.springframework.transaction.config.internalTransactionAdvisor 判断当前registry 是否包含名为org.springframework.transaction.config.internalTransactionAdvisor的beanDefinition , 如果没有则进入逻辑。

  1. 创建AnnotationTransactionAttributeSource的BeanDefinition
  2. 创建TransactionInterceptor的BeanDefinition
  3. 将AnnotationTransactionAttributeSource 添加到TransactionInterceptor的属性中(运行时属性注入)
  4. 调用registerTransactionManager将给TransactionAspectSupport的属性transactionManagerBeanName赋值
  5. 创建BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition
  6. 将TransactionInterceptor和AnnotationTransactionAttributeSource添加到BeanFactoryTransactionAttributeSourceAdvisor的属性中(运行时注入)
  7. 创建CompositeComponentDefinition并将上述三个BeanDefinition包装为BeanComponentDefinition的BeanDefinition然后调用compositeDef.addNestedComponent添加到CompositeComponentDefinition中

至此tx标签的解析工作已经完毕 , 下面看Spring是如何切到相应的方法并开始事务 , 提交 , 回滚的.

四、AnnotationAwareAspectJAutoProxyCreator 解析

AnnotationAwareAspectJAutoProxyCreator类图

可以看到AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor , BeanFactoryAware 接口 , 继承ProxyProcessorSupport类, 那么这三个类/接口都是有什么作用呢?

SmartInstantiationAwareBeanPostProcessor继承了接口BeanPostProcessor , BeanPostProcessor 的中有两个方法: postProcessBeforeInitialization和postProcessAfterInitialization , 主要在bean 加载前后做一些操作 , 我们这里只需看AbstractAutoProxyCreator.postProcessAfterInitialization

在这里插入图片描述

接着重点看下 wrapIfNecessary 这个方法:
在这里插入图片描述

这个方法主要有 以下代码:

 Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);

顺着代码调用, 找到AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply 方法------>>>>AopUtils#findAdvisorsThatCanApply 方法

在这里插入图片描述
这里遍历 所有的 advisor , 判断是否为IntroductionAdvisor 类型的 , Spring事务用到的advisor是BeanFactoryTransactionAttributeSourceAdvisor (本文3.2所示代码中声明的) , 之后关注这行代码

if (!(candidate instanceof IntroductionAdvisor) && canApply(candidate, clazz, hasIntroductions)) {
                    eligibleAdvisors.add(candidate);
 }

我们的candidate 是PointcutAdvisor 类型的advisor。 ( 有关pointcutAdvisor和inadvisor的advisor区别)

在这里插入图片描述
关注下canApply方法:

org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)

这里第一个入参为 Pointcut(Spring Aop 相关概念讲解)。
BeanFactoryTransactionAttributeSourceAdvisor的pointcut为TransactionAttributeSourcePointcut , 具体如图:
在这里插入图片描述

canApply方法具体:

在这里插入图片描述

这里的 methodMatcher 为 TransactionAttributeSourcePointcut , 现在看matches方法

@Override
public boolean matches(Method method, Class<?> targetClass) {
     //这里getTransactionAttributeSource 返回 transactionAttributeSource 为 AnnotationTransactionAttributeSource
     //这是在本文3.2位置 , Spring代码SpringAnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator 中声明的
	TransactionAttributeSource tas = getTransactionAttributeSource();
	//如果当前TransactionAttributeSource 为空或者tas.getTransactionAttribute不为空则返回true, 即匹配 , 创建代理对象
	return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

接下来看 getTransactionAttribute , 发现AnnotationTransactionAttributeSource 没有此方法, 找到其父类AbstractFallbackTransactionAttributeSource有getTransactionAttribute , 继续沿着此方法一直追 , 追到SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement) , 为什么是SpringTransactionAnnotationParser 是在AnnotationTransactionAttributeSource 中声明的 , 至此就回到了本文刚开始的时候了.
在这里插入图片描述

以上逻辑完成了对类方法的筛选 , 如果有@Transactional 注解 , 那么解析其属性 , 将TransactionAttribute 以method和class 关键信息保存起来

final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<Object, TransactionAttribute>(1024);

, 到TransactionInterceptor (Advice) 执行invoke 方法时再获取

final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);

结束语: 一开始以为自己懂了, 当想点做好事把这个思路分享出来时 , 写文的过程中又会发现原来的理解有一些错误, 然后再探究, 修正, 最后完成 , 逻辑还是有些乱 , 不过研究源码的路就是这样 , 找一个自己容易理解的方向, 找的过程也不可避免地跳跃 , 中断 , 即时去查询相应的知识点 , 到最后很有收获 , 只要啃下来就好了. (^_^)


经过深度思考的梳理一定会让你收获颇丰^_^


版权声明:本文为HLhakey原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。