注:本系列源碼分析基於spring 5.2.2.RELEASE,本文的分析基於 annotation 註解方式,gitee倉庫鏈接:funcy/spring-framework.
在spring事務之認識事務組件一文中,我們通過一個demo演示瞭如何使用spring事務管理功能,然後分析了@EnableTransactionManagement
註解的功能,本文將繼續分析spring事務相關代碼。
1. 代理對象創建流程
spring 事務管理功能是基於aop的,使用代理對象來進行事務的一系列操作,本文將通過調試的方式來分析代理對象的創建過程。
在spring事務之認識事務組件中我們通過分析@EnableTransactionManagement
註解,發現該註解會向spring容器中註冊InfrastructureAdvisorAutoProxyCreator
,這個類是AbstractAdvisorAutoProxyCreator
的子類,用來生成代理對象的,本節將基於InfrastructureAdvisorAutoProxyCreator
來分析對象的創建過程。
關於
AbstractAdvisorAutoProxyCreator
的分析以及代理對象的生成,在 spring aop 之 AnnotationAwareAspectJAutoProxyCreator 分析(上) 與 spring aop 之 AnnotationAwareAspectJAutoProxyCreator 分析(下)已經作了詳細分析,這裏我們主要分析與aop有差異的地方,需要詳細瞭解spring aop代理對象如何產生的小夥伴,可以閱讀上述兩篇文章。
我們依舊是進入AbstractAutoProxyCreator#postProcessBeforeInitialization
:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
...
if (...) {
//1. shouldSkip:
// - AspectJAwareAdvisorAutoProxyCreator 的 shouldSkip 方法會處理 @Aspect 註解的類,
// 將其中的@Before/@After/@Around等註解包裝爲Advisor,再調用父類(也就是
// AbstractAutoProxyCreator)的shouldSkip方法
// - InfrastructureAdvisorAutoProxyCreator直接執行AbstractAutoProxyCreator的shouldSkip方法
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
if(...) {
...
// 2. getAdvicesAndAdvisorsForBean:獲取適用用於當前對象的advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(
beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
...
return proxy;
}
return null;
}
這個方法有兩處不同點,代碼中已經註明了其中的差異,關於shouldSkip
,沒啥好說的,我們重點展開getAdvicesAndAdvisorsForBean(...)
方法。
1.1 BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
一路跟進getAdvicesAndAdvisorsForBean(...)
方法,其中的操作與AspectJAwareAdvisorAutoProxyCreator
的操作並不太大區別,不過有個方法個人認爲需要強調下,方法如下:
BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// 查找當前beanFactory中所有 Advisor 的 bean class
// Advisor可以是用戶實現Advisor相關接口,也可以是xml指定的
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
...
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
...
// 根據advisor的bean name,從spring容器中獲取 bean
advisors.add(this.beanFactory.getBean(name, Advisor.class));
...
}
...
return advisors;
}
這個方法主要的作用是獲取spring容器中的所有advisor
,其實在AnnotationAwareAspectJAutoProxyCreator
中也是這麼獲取的,只不過在獲取前,AnnotationAwareAspectJAutoProxyCreator
會在shouldSkip(...)
方法中把@Aspect
類中包含@Befor/@After/@Around
等註解的方法包裝成對應的Advisor
,而InfrastructureAdvisorAutoProxyCreator
則不會,本節一開始也提到過了。
在spring事務之認識事務組件一文中,分析@EnableTransactionManagement
註解功能時,我們分析到該註解會通過@Bean
註解向spring中引入BeanFactoryTransactionAttributeSourceAdvisor
,這個bean就會在BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
被獲取到。
1.2 AopUtils#canApply(...)
跟着方法一路往下走,接着就來到了判斷advisor
能否適用於目標class
的地方了:
/**
* 判斷advisor能否適用於目標class
*/
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
...
// 判斷是否爲 PointcutAdvisor,處理事務的advisor爲BeanFactoryTransactionAttributeSourceAdvisor,
// 它實現了PointcutAdvisor,因此下面的代碼會執行
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//使用 PointcutAdvisor 繼續判斷
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
...
}
/**
* 判斷advisor能否適用於目標class
*/
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//1. 切點上是否存在排除類的配置
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// 獲取方法匹配對象,MethodMatcher.TRUE 爲默認的 MethodMatcher 對象
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
...
// classes包含targetClass、除Object的所有父類、所有接口
Set<Class<?>> classes = new LinkedHashSet<>();
// 省略獲取targetClass的父類步驟
...
for (Class<?> clazz : classes) {
// 獲取 clazz 定義的方法,包括當前類的方法、除Object外的所有父類方法、接口的默認方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 2. 匹配的關鍵在這裏
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
這一塊的代碼與AnnotationAwareAspectJAutoProxyCreator
一模一樣,他們都是調用同樣的方法來判斷,但由於傳入的的advisor
不同,最終調用到的具體的匹配規則也不相同。
從代碼的分析來看,匹配的邏輯都在Pointcut
中,而Pointcut
又來自於Advisor
,可見Advisor
十分關鍵。處理事務的Advisor
爲BeanFactoryTransactionAttributeSourceAdvisor
,接下來我們就來分析這個類。
1.3 BeanFactoryTransactionAttributeSourceAdvisor
匹配規則分析
從上一小 節的分析中,我們知道判斷targetClass
能否應用當前advisor
的規則來源於advisor
的pointcut
,pointcut
有兩個地方包含了判斷規則:
- 匹配類:
pc.getClassFilter().matches(targetClass)
- 匹配方法:
pc.getMethodMatcher().matches(method, targetClass)
這一小 節我們從 BeanFactoryTransactionAttributeSourceAdvisor
入手,一步步分析匹配規則。
public class BeanFactoryTransactionAttributeSourceAdvisor
extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
/**
* 這個就是 pointcut
*/
private final TransactionAttributeSourcePointcut pointcut =
new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
/**
* 設置 transactionAttributeSource
*/
public void setTransactionAttributeSource(TransactionAttributeSource
transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
/**
* 設置 ClassFilter
*/
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
/**
* 獲取 pointcut
*/
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
上面的代碼關鍵部分已經註釋了,這裏來總結下:BeanFactoryTransactionAttributeSourceAdvisor#getPointcut
得到的 pointcut
爲TransactionAttributeSourcePointcut
,就是在private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {...}
中創建的。
BeanFactoryTransactionAttributeSourceAdvisor
的transactionAttributeSource
是什麼呢?回憶下ProxyTransactionManagementConfiguration
中創建transactionAdvisor
的代碼:
public class ProxyTransactionManagementConfiguration
extends AbstractTransactionManagementConfiguration {
// 省略其他
...
/**
* 讀取Spring的 @Transactional 註解,並將相應的事務屬性公開給Spring的事務基礎結構
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
/**
* 事務增強器.
* transactionAttributeSource:transactionAttributeSource() 返回的對象
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource,
TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor =
new BeanFactoryTransactionAttributeSourceAdvisor();
// 設置事務屬性類,用來保存 @Transactional 的屬性
advisor.setTransactionAttributeSource(transactionAttributeSource);
...
return advisor;
}
}
由此可知,BeanFactoryTransactionAttributeSourceAdvisor
的transactionAttributeSource
屬性爲AnnotationTransactionAttributeSource
.
我們再回到BeanFactoryTransactionAttributeSourceAdvisor
,從上面的分析可知,getPointcut()
得到的是TransactionAttributeSourcePointcut
對象,然後進入這個類:
abstract class TransactionAttributeSourcePointcut
extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
// 在構造方法中設置 ClassFilter
setClassFilter(new TransactionAttributeSourceClassFilter());
}
/**
* pointcut 的 matches 方法
*/
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 得到的結果爲AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
/**
* 在 BeanFactoryTransactionAttributeSourceAdvisor 中已指定
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
/**
* 內部類,實現了 ClassFilter
*/
private class TransactionAttributeSourceClassFilter implements ClassFilter {
/**
* ClassFilter 的 matches
*/
@Override
public boolean matches(Class<?> clazz) {
// 是否爲TransactionalProxy、PlatformTransactionManager、PersistenceExceptionTranslator的實現類
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
PlatformTransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
//判斷 TransactionAttributeSource 獲取事務屬性是否爲空
// 得到的結果爲AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
從上面的方法,我們得到了一個重要的規則:
- 匹配類:
pc.getClassFilter().matches(targetClass)
,ClassFilter
爲TransactionAttributeSourceClassFilter
匹配類的規則是找到了,那匹配方法的規則呢?我們進入TransactionAttributeSourcePointcut#getMethodMatcher()
方法,進入的是StaticMethodMatcherPointcut
:
public abstract class StaticMethodMatcherPointcut
extends StaticMethodMatcher implements Pointcut {
// 省略了一些代碼
...
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}
}
返回的竟然是this
!這是個啥?不要慌,再細看TransactionAttributeSourcePointcut
,發現它繼承了StaticMethodMatcherPointcut
:
abstract class TransactionAttributeSourcePointcut
extends StaticMethodMatcherPointcut implements Serializable {
// 省略了一些代碼
...
}
所以,pc.getMethodMatcher()
得到的就是TransactionAttributeSourcePointcut
,其mathes(...)
方法就是TransactionAttributeSourcePointcut#matches
.
在本小節的最後,我們來總結下分析的結果:
- 匹配類:
pc.getClassFilter().matches(targetClass)
,ClassFilter
爲TransactionAttributeSourceClassFilter
; - 匹配方法:
pc.getMethodMatcher().matches(method, targetClass)
,methodMatcher
爲TransactionAttributeSourcePointcut
; - 在上面兩個規則中,都會調用
TransactionAttributeSourcePointcut#getTransactionAttributeSource
,這個方法返回的結果爲AnnotationTransactionAttributeSource
.
1.4 匹配流程
在 1.2 部分,我們知道,當前advisor
能否應用於目標class,需要同時滿足兩個匹配規則:
- 匹配類:
pc.getClassFilter().matches(targetClass)
,ClassFilter
爲TransactionAttributeSourceClassFilter
; - 匹配方法:
pc.getMethodMatcher().matches(method, targetClass)
,methodMatcher
爲TransactionAttributeSourcePointcut
;
我們來看下這兩個方法:
TransactionAttributeSourceClassFilter#matches
:先判斷當前類是否爲是否爲TransactionalProxy
、PlatformTransactionManager
、PersistenceExceptionTranslator
或其實現類,然後調用AnnotationTransactionAttributeSource#isCandidateClass
繼續判斷;TransactionAttributeSourcePointcut#matches
:調用AnnotationTransactionAttributeSource#getTransactionAttribute
(由於繼承關係,實際調用的是AbstractFallbackTransactionAttributeSource#getTransactionAttribute
)判斷。
接下來我們就來分析下具體匹配流程。
AnnotationTransactionAttributeSource#isCandidateClass
讓我們直奔主題,進入isCandidateClass
方法:
AnnotationTransactionAttributeSource#isCandidateClass
@Override
public boolean isCandidateClass(Class<?> targetClass) {
// 找到所有的annotationParsers,循環匹配
for (TransactionAnnotationParser parser : this.annotationParsers) {
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
}
可以看到,這是在循環裏調用TransactionAnnotationParser
的isCandidateClass
方法。this.annotationParsers
是啥呢?通過調試,內容如下:
this.annotationParsers
中只有SpringTransactionAnnotationParser
,我們進入其isCandidateClass
方法:
public class SpringTransactionAnnotationParser
implements TransactionAnnotationParser, Serializable {
/**
* 判斷類上是否有 @Transactional 註解
*/
@Override
public boolean isCandidateClass(Class<?> targetClass) {
return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}
}
這個方法最終調用的是AnnotationUtils.isCandidateClass
,用來判斷指定的類上是否有@Transactional
註解。
到這裏,我們就明白了,TransactionAttributeSourceClassFilter#matches
先排除一些類(TransactionalProxy
/PlatformTransactionManager
/PersistenceExceptionTranslator
及其子類)後,最終會匹配帶有@Transactional
註解的類。
AnnotationTransactionAttributeSource#getTransactionAttribute
上面的方法匹配成功後,並不能表示成功匹配,還得匹配TransactionAttributeSourcePointcut#matches
,兩者同時滿足纔會匹配成功。TransactionAttributeSourcePointcut#matches
調用AnnotationTransactionAttributeSource#getTransactionAttribute
完成匹配的,我們跟進去:
public abstract class AbstractFallbackTransactionAttributeSource
implements TransactionAttributeSource {
/**
* 獲取 @Transactional 註解的屬性
*/
public TransactionAttribute getTransactionAttribute(Method method,
@Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// 省略從緩存中獲取
...
else {
// 獲取 Transaction 屬性,即 @Transactional 註解的屬性
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// 省略放入緩存操作
...
return txAttr;
}
}
}
AnnotationTransactionAttributeSource
的getTransactionAttribute
是繼承自AbstractFallbackTransactionAttributeSource
的,因此我們進入的方法是AbstractFallbackTransactionAttributeSource#getTransactionAttribute
,這個方法用來獲取方法上的@Transactional
註解的屬性,我們跟進computeTransactionAttribute(...)
:
AbstractFallbackTransactionAttributeSource
protected TransactionAttribute computeTransactionAttribute(Method method,
@Nullable Class<?> targetClass) {
// 默認必須要 public 方法才支持事務
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// 1. 獲取確切的方法,例如傳入的class是IFoo,實際的的class是DefaultFoo,
// 那麼應該將 IFoo#method 轉換爲 DefaultFoo#method
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 2. 從方法上獲取 @Transactional 的屬性
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// 3. 從類上獲取 @Transaction 的屬性
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// 4. 確切的方法上找不到,就找傳入的方法上的
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// 5. 以上都沒找到,就找確切的類上的
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
// 6. 沒有獲取到,最終返回null
return null;
}
從以上方法的流程,可總結獲取 @Transactional
屬性流程如下:
- 將傳入的方法轉換爲確切的方法,例如傳入的
class
是IFoo
,實際的的class
是DefaultFoo
,這裏就會將IFoo#method
轉換爲DefaultFoo#method
- 從確切的方法上獲取
@Transactional
的屬性 - 如果沒有獲取到,就從確切的從類上獲取
@Transaction
的屬性 - 如果沒有獲取到,就傳入的方法上獲取
@Transaction
的屬性 - 如果沒有獲取到,就傳入的類上獲取
@Transaction
的屬性 - 如果以上都沒有獲取到,就返回
null
spring又是如何從方法或類上獲取 @Transactional
的屬性呢?繼續看下去:
AnnotationTransactionAttributeSource
// 從方法上獲取 @Transactional 屬性
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
// 從類上獲取 @Transactional 屬性
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
// 最終調用的方法
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
// 解析 @Transactional 註解的屬性
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
最終他們都是調用AnnotationTransactionAttributeSource#determineTransactionAttribute
來獲取的,而在AnnotationTransactionAttributeSource#determineTransactionAttribute
調用了TransactionAnnotationParser#parseTransactionAnnotation
方法。對於this.annotationParsers
還眼熟嗎,在前面已經分析過了,裏面只有一個類:SpringTransactionAnnotationParser
,我們跟進去:
SpringTransactionAnnotationParser
/**
* 獲取 Transactional 註解,存在則繼續解析,不存在則返回 null
*/
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 獲取 Transactional 註解,存在則繼續解析,不存在則返回 null
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
/**
* 解析 Transactional 註解的具體操作
*/
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
// 事務的傳播方式
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
// 事務的隔離級別
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
// 事務的超時時間
rbta.setTimeout(attributes.getNumber("timeout").intValue());
// 是否爲只讀
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
// 處理回滾異常
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
// 處理不回滾異常
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
可以看到,Transactional
註解的各屬性解析成了RuleBasedTransactionAttribute
.
至此,我們就明白了,TransactionAttributeSourcePointcut#matches
就是用來判斷類或方法上有沒有Transactional
註解。
1.5 代理對象的創建
代理對象的創建在AbstractAutoProxyCreator#postProcessAfterInitialization
方法中完成的,這個流程同aop流程真的是一模一樣,這裏就不再分析了,想了解的小夥伴可查看spring aop 之 AnnotationAwareAspectJAutoProxyCreator 分析(下)。
2. 方法的執行
方法的執行方面,事務與aop的執行流程並無區別,一樣是通過Advisor
找到對應的Advice
,再通過Advice
找到對應的 methodInterceptor
,最終執行的是MethodInterceptor#invoke
方法,在事務這裏MethodInterceptor
爲TransactionInterceptor
,這個類是在ProxyTransactionManagementConfiguration
中通過@Bean
註解引入的。
關於aop的流程,我們並不打算分析,相關分析在 spring aop之jdk動態代理 與 spring aop之cglib 代理 已有詳細分析,感興趣的小夥伴可自行查閱,這裏我們直接來看TransactionInterceptor#invoke
的執行流程。
事務的處理的流程在TransactionInterceptor#invoke
方法中:
TransactionInterceptor#invoke
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null
? AopUtils.getTargetClass(invocation.getThis()) : null);
// 繼續往下看
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
真正的處理邏輯在 TransactionAspectSupport#invokeWithinTransaction
方法中:
TransactionAspectSupport#invokeWithinTransaction
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = getTransactionAttributeSource();
// 獲取@Transactional的屬性配置
final TransactionAttribute txAttr = (tas != null
? tas.getTransactionAttribute(method, targetClass) : null);
// 獲取事務管理器(IOC容器中獲取)
final TransactionManager tm = determineTransactionManager(txAttr);
// 省略 ReactiveTransactionManager 的處理
...
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 獲取方法的全限定名,格式爲:"包名.類型.方法名"
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 事務的處理邏輯,這也是我們接下來主要分析的地方
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// 1. 開啓事務
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// 2. 執行具體的業務
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 3. 異常回滾
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 重置事務信息
cleanupTransactionInfo(txInfo);
}
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 4. 提交事務,代碼中會判斷是否能支持
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
// 省略其他
...
}
}
以上方法就是事務的全部流程了,步驟如下:
- 開啓事務
- 執行業務代碼
- 異常回滾
- 提交事務
關於事務的具體分析,我們將在下一篇文章分析,本文只需要對事務的處理流程有大致瞭解即可。
3. 總結
本文主要分析了事務中代理對象的創建及執行流程,實際上這些步驟同aop基本一致,本文着重分析了與aop不同的部分:
-
在代理對象的創建方面,分析瞭如何判斷當前方法能否使用
BeanFactoryTransactionAttributeSourceAdvisor
,重點分析了TransactionAttributeSourceClassFilter#matches
與TransactionAttributeSourcePointcut#matches
方法,這是判斷的核心所在; -
在方法的執行上的,粗略分析了
TransactionInterceptor#invoke
的執行流程,這些事務的開啓、提交、異常回滾等流程跟我們平常使用的差別不大,不過裏面的具體細節我們並沒有分析。
本文重點是代理對象的創建及執行流程,事務執行的具體細節我們下篇再分析。
本文原文鏈接:https://my.oschina.net/funcy/blog/4773457 ,限於作者個人水平,文中難免有錯誤之處,歡迎指正!原創不易,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
本系列的其他文章