【spring源碼分析】spring事務(二):事務的執行流程

注:本系列源碼分析基於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十分關鍵。處理事務的AdvisorBeanFactoryTransactionAttributeSourceAdvisor,接下來我們就來分析這個類。

1.3 BeanFactoryTransactionAttributeSourceAdvisor 匹配規則分析

從上一小 節的分析中,我們知道判斷targetClass能否應用當前advisor的規則來源於advisorpointcutpointcut有兩個地方包含了判斷規則:

  • 匹配類: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 得到的 pointcutTransactionAttributeSourcePointcut,就是在private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {...}中創建的。

BeanFactoryTransactionAttributeSourceAdvisortransactionAttributeSource是什麼呢?回憶下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;
    }

}

由此可知,BeanFactoryTransactionAttributeSourceAdvisortransactionAttributeSource屬性爲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)ClassFilterTransactionAttributeSourceClassFilter

匹配類的規則是找到了,那匹配方法的規則呢?我們進入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)ClassFilterTransactionAttributeSourceClassFilter
  • 匹配方法:pc.getMethodMatcher().matches(method, targetClass)methodMatcherTransactionAttributeSourcePointcut
  • 在上面兩個規則中,都會調用TransactionAttributeSourcePointcut#getTransactionAttributeSource,這個方法返回的結果爲AnnotationTransactionAttributeSource.

1.4 匹配流程

在 1.2 部分,我們知道,當前advisor能否應用於目標class,需要同時滿足兩個匹配規則:

  • 匹配類:pc.getClassFilter().matches(targetClass)ClassFilterTransactionAttributeSourceClassFilter
  • 匹配方法:pc.getMethodMatcher().matches(method, targetClass)methodMatcherTransactionAttributeSourcePointcut

我們來看下這兩個方法:

  • TransactionAttributeSourceClassFilter#matches:先判斷當前類是否爲是否爲TransactionalProxyPlatformTransactionManagerPersistenceExceptionTranslator或其實現類,然後調用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;
}

可以看到,這是在循環裏調用TransactionAnnotationParserisCandidateClass方法。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;
        }
    }
}

AnnotationTransactionAttributeSourcegetTransactionAttribute是繼承自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 屬性流程如下:

  1. 將傳入的方法轉換爲確切的方法,例如傳入的classIFoo,實際的的classDefaultFoo,這裏就會將 IFoo#method 轉換爲 DefaultFoo#method
  2. 從確切的方法上獲取 @Transactional 的屬性
  3. 如果沒有獲取到,就從確切的從類上獲取 @Transaction 的屬性
  4. 如果沒有獲取到,就傳入的方法上獲取 @Transaction 的屬性
  5. 如果沒有獲取到,就傳入的類上獲取 @Transaction 的屬性
  6. 如果以上都沒有獲取到,就返回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方法,在事務這裏MethodInterceptorTransactionInterceptor,這個類是在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 {
        // 省略其他
        ...
    }
}

以上方法就是事務的全部流程了,步驟如下:

  1. 開啓事務
  2. 執行業務代碼
  3. 異常回滾
  4. 提交事務

關於事務的具體分析,我們將在下一篇文章分析,本文只需要對事務的處理流程有大致瞭解即可。

3. 總結

本文主要分析了事務中代理對象的創建及執行流程,實際上這些步驟同aop基本一致,本文着重分析了與aop不同的部分:

  • 在代理對象的創建方面,分析瞭如何判斷當前方法能否使用BeanFactoryTransactionAttributeSourceAdvisor,重點分析了TransactionAttributeSourceClassFilter#matchesTransactionAttributeSourcePointcut#matches 方法,這是判斷的核心所在;

  • 在方法的執行上的,粗略分析了TransactionInterceptor#invoke的執行流程,這些事務的開啓、提交、異常回滾等流程跟我們平常使用的差別不大,不過裏面的具體細節我們並沒有分析。

本文重點是代理對象的創建及執行流程,事務執行的具體細節我們下篇再分析。


本文原文鏈接:https://my.oschina.net/funcy/blog/4773457 ,限於作者個人水平,文中難免有錯誤之處,歡迎指正!原創不易,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

本系列的其他文章

【spring源碼分析】spring源碼分析系列文章

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