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);

結束語: 一開始以爲自己懂了, 當想點做好事把這個思路分享出來時 , 寫文的過程中又會發現原來的理解有一些錯誤, 然後再探究, 修正, 最後完成 , 邏輯還是有些亂 , 不過研究源碼的路就是這樣 , 找一個自己容易理解的方向, 找的過程也不可避免地跳躍 , 中斷 , 即時去查詢相應的知識點 , 到最後很有收穫 , 只要啃下來就好了. (^_^)


經過深度思考的梳理一定會讓你收穫頗豐^_^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章