Spring事務管理 @Transactional 註解管理事務原理深度剖析
一、 @Transactional 註解解析
方法入口:SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)
下面看 parseTransactionAnnotation方法做了什麼 :
parseTransactionAnnotation 方法的作用是將註解中聲明的屬性都解析加入到 RuleBasedTransactionAttribute 中
並return 給調用者.
二、爲什麼是SpringTransactionAnnotationParser 解析Transactional註解 , 從哪裏來的?
查看 SpringTransactionAnnotationParser 的引用 , 只有 AnnotationTransactionAttributeSource 的構造方法中有
三、那麼爲什麼是 AnnotationTransactionAttributeSource ?
這我們就不得不從 <tx:annotation-driven transaction-manager=“transactionManager”/> 講起了(spring 是如何處理各種xml標籤的,由誰解析, 這裏不再贅述)
看 TxNamespaceHandler
然後到 AnnotationDrivenBeanDefinitionParser , 看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 , 如果沒有則進入邏輯。
- 創建AnnotationTransactionAttributeSource的BeanDefinition
- 創建TransactionInterceptor的BeanDefinition
- 將AnnotationTransactionAttributeSource 添加到TransactionInterceptor的屬性中(運行時屬性注入)
- 調用registerTransactionManager將給TransactionAspectSupport的屬性transactionManagerBeanName賦值
- 創建BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition
- 將TransactionInterceptor和AnnotationTransactionAttributeSource添加到BeanFactoryTransactionAttributeSourceAdvisor的屬性中(運行時注入)
- 創建CompositeComponentDefinition並將上述三個BeanDefinition包裝爲BeanComponentDefinition的BeanDefinition然後調用compositeDef.addNestedComponent添加到CompositeComponentDefinition中
至此tx標籤的解析工作已經完畢 , 下面看Spring是如何切到相應的方法並開始事務 , 提交 , 回滾的.
四、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);
結束語: 一開始以爲自己懂了, 當想點做好事把這個思路分享出來時 , 寫文的過程中又會發現原來的理解有一些錯誤, 然後再探究, 修正, 最後完成 , 邏輯還是有些亂 , 不過研究源碼的路就是這樣 , 找一個自己容易理解的方向, 找的過程也不可避免地跳躍 , 中斷 , 即時去查詢相應的知識點 , 到最後很有收穫 , 只要啃下來就好了. (^_^)
經過深度思考的梳理一定會讓你收穫頗豐^_^