1. 程式人生 > >Spring系列(六):Spring事務原始碼解析

Spring系列(六):Spring事務原始碼解析

一、事務概述

  1.1 什麼是事務

  事務是一組原子性的SQL查詢,或者說是一個獨立的工作單元。要麼全部執行,要麼全部不執行。

  1.2 事務的特性(ACID)

  ①原子性(atomicity)

   一個事務必須被視為一個不可分割的最小工作單元,整個事務中的所有操作要麼全部提交成功,要麼全部回滾,對於一個事務來說,不可能只執行其中的一部分操作

  ②一致性(consistency)

  資料庫總是從一個一致性的狀態轉換到另外一個一致性的狀態。

  ③隔離性(isolation)

  一個事務所做的修改在最終提交以前,對其他事務是不可見的。也就是說多個併發事務之間要相互隔離。

  ④永續性(durability)

  一旦事務提交,則其所做的修改就會永久的儲存在資料庫中,接下來即使資料庫系統崩潰了,修改的資料也不會丟失

  1.3 事務的隔離級別

  ①讀未提交(READ UNCOMMITTED)

   事務中的修改,即使沒有提交,對其他事務也是可見的,也就是說事務可以讀取到未提交的資料,這也被稱為髒讀。

  ②讀已提交(READ COMMITTED)

  一個事務從開始到提交之前,所做的任何修改對其他事務都是不可見的,這個級別有時候也叫不可重複讀,因為兩次執行同樣的查詢,可能會得到不一樣的結果。

  ③可重複讀(REPEATABLE READ)

  該隔離級別保證了在同一個事務中多次讀取同樣的記錄的結果是一致的,但是無法解決另外一個幻讀的問題,所謂的幻讀就是指當某個事務在讀取某個範圍內的記錄是,另外一個事務又在該範圍內插入了新的記錄,當之前的事務再次讀取該範圍的記錄時就會產生幻行。

  ④可序列化(SERIALIZABLE)

  SERIALIZABLE是最高的隔離級別,通過強制事務的序列執行,避免了前面說的幻讀問題,簡單來說,SERIALIZABLE會在讀取的每一行資料上加上鎖。

二、Spring事務關鍵介面

  1 PlatformTransactionManager 事務管理器

public interface PlatformTransactionManager {

    /**
     * 獲取事務
     */
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    /**
     * 提交
     */
    void commit(TransactionStatus status) throws TransactionException;

    /**
     * 回滾
     */
    void rollback(TransactionStatus status) throws TransactionException;

}

  2 TransactionDefinition 事務定義資訊

public interface TransactionDefinition {

    /**
     * Support a current transaction; create a new one if none exists. 支援當前事物,若當前沒有事物就建立一個事物
     */
    int PROPAGATION_REQUIRED = 0;

    /**
     * Support a current transaction; execute non-transactionally if none exists. 如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式執行
     */
    int PROPAGATION_SUPPORTS = 1;

    /**
     * Support a current transaction; throw an exception if no current transaction exists. 如果當前存在事務,則加入該事務;如果當前沒有事務,則丟擲異常
     */
    int PROPAGATION_MANDATORY = 2;

    /**
     * Create a new transaction, suspending the current transaction if one exists.建立一個新的事務,如果當前存在事務,則把當前事務掛起
     */
    int PROPAGATION_REQUIRES_NEW = 3;

    /**
     * Do not support a current transaction; rather always execute non-transactionally.以非事務方式執行,如果當前存在事務,則把當前事務掛起
     */
    int PROPAGATION_NOT_SUPPORTED = 4;

    /**
     * Do not support a current transaction; throw an exception if a current transaction exists. 以非事務方式執行,如果當前存在事務,則丟擲異常
     */
    int PROPAGATION_NEVER = 5;

    /**
     * Execute within a nested transaction if a current transaction exists.如果外層存在事務,就以巢狀事務執行,被巢狀的事務可以獨立於外層事務進行提交或者回滾(儲存點),
如果外層不存在事務,行為跟PROPAGATION_REQUIRES_NEW
     */
    int PROPAGATION_NESTED = 6;


    /**
     * Use the default isolation level of the underlying datastore. 使用資料庫預設的隔離級別
   */ int ISOLATION_DEFAULT = -1; /** * 讀未提交
   */ int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED; /** * 讀已提交
   */ int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED; /** * 可重複讀*/ int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ; /** * 可序列化
   */ int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE; /** * 使用預設的超時時間 */ int TIMEOUT_DEFAULT = -1; /** * 獲取事物的傳播行為
*/ int getPropagationBehavior(); /** * 獲取事物的隔離級別
   */ int getIsolationLevel(); /** * 獲取事物的超時時間
   */ int getTimeout(); /** * 是否為只讀事物
*/ boolean isReadOnly(); /** * 獲取當前事物的名稱
   */ String getName(); }

  3 TransactionStatus 事務執行狀態

public interface TransactionStatus extends SavepointManager, Flushable {

    /**
     * 是否為新事務
     */
    boolean isNewTransaction();

    /**
     * 是否有儲存點*/
    boolean hasSavepoint();

    /**
     * 設定為只回滾*/
    void setRollbackOnly();

    /**
     * 是否為只回滾
     */
    boolean isRollbackOnly();

    /**
     * 講會話重新整理到資料庫中
     */
    @Override
    void flush();

    /**
     * 當前事務是否已經完成*/
    boolean isCompleted();

}

三、Spring事務啟動過程

  1 @EnableTransactionManagement

  1.1 在主配置類中新增@EnableTransactionManagement註解,開啟Spring事務的支援,配置如下:

@EnableTransactionManagement
@ComponentScan(basePackages = {"com.toby"})
public class TransactionConfig {
    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("123qwe");
        dataSource.setUrl("jdbc:mysql://localhost:3306/demo_db?useUnicode=true&characterEncoding=utf-8&useSSL=false");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

  1.2 @EnableTransactionManagement 到底做了什麼?

  原始碼解析跟Spring系列(五):Spring AOP原始碼解析中的@EnableAspectJAutoProxy註解一樣,可以參考下。主要給Spring容器加入如下元件:

   2 InfrastructureAdvisorAutoProxyCreator(重點)

  2.1 首先看下類繼承圖

   2.2 實現了InstantiationAwareBeanPostProcessor介面

  該介面有2個方法postProcessBeforeInstantiation和postProcessAfterInstantiation,其中例項化之前會執行postProcess BeforeInstantiation方法:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        //構建我們的快取key
        Object cacheKey = getCacheKey(beanClass, beanName);

        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            //如果被解析過直接返回
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            /**
             * 判斷是不是基礎的bean
             * 判斷是不是應該跳過 (此處Spring Aop解析直接解析出我們的切面資訊(並且把我們的切面資訊進行快取),
        * 而事務在這裡是不會解析的,為什麼?原因事務的話已經把事務攔截器通過@Bean,而Aop的需要尋找) */ if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }  

  2.3 實現了BeanPostProcessor介面

   該介面有2個方法postProcessBeforeInitialization和postProcessAfterInitialization,其中元件初始化之後會執行postProcessAfterInitialization(該方法建立Aop和事務的代理物件)方法:

/**
     * 在該後置方法中 我們的事務和aop的代理物件都是在這生成的
     * @param bean bean例項
     * @param beanName bean的名稱
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if (bean != null) {
            //獲取快取key
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //如果有必要就代理
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

  進去wrapIfNecessary(bean, beanName, cacheKey)方法:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //已經被處理過
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        //不需要增強的
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        //是不是基礎的bean 是不是需要跳過的
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        //如果有匹配的通知,就建立代理物件
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        //如果不為空,表述需要代理
        if (specificInterceptors != DO_NOT_PROXY) {
            //設定當前的物件已處理
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //建立我們的真正的代理物件
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            //加入到快取
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

  進入getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)方法:

protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        /**
         * 找合適的增強器物件
         */
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        //若合適的通知器為空
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

  進入findEligibleAdvisors(beanClass, beanName)方法:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //找到Spring IoC容器中所有的候選通知 包括Aop的和事務的
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //判斷找到的通知能不能作用到當前的類上
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        //對我們的advisor進行排序
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

  ① 進入findCandidateAdvisors()方法,通過增強器檢索器檢索增強器:

   進入findAdvisorBeans()方法:

public List<Advisor> findAdvisorBeans() {

        String[] advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            /**
             * 去容器中獲取到實現了Advisor介面的實現類 我們的事務註解@EnableTransactionManagement匯入了一個叫ProxyTransactionManagementConfiguration配置類
             * 而在這個配置類中配置了:
             * @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
             * @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
             * public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor();
             * 然後把他的名字獲取出來儲存到 本類的屬性變數cachedAdvisorBeanNames中
             */
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
        //若在容器中沒有找到,直接返回一個空的集合
        if (advisorNames.length == 0) {
            return new ArrayList<>();
        }

        List<Advisor> advisors = new ArrayList<>();
        //容器中找到了我們事務配置的BeanFactoryTransactionAttributeSourceAdvisor
        for (String name : advisorNames) {
            //判斷他是不是一個合適的
            if (isEligibleBean(name)) {
                //BeanFactoryTransactionAttributeSourceAdvisor是不是正在建立的Bean
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Skipping currently created advisor '" + name + "'");
                    }
                }
                //不是的話
                else {
                    try {
                        //顯示的呼叫getBean方法方法建立我們的BeanFactoryTransactionAttributeSourceAdvisor返回去
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    }
                    catch (BeanCreationException ex) {
                        Throwable rootCause = ex.getMostSpecificCause();
                        if (rootCause instanceof BeanCurrentlyInCreationException) {
                            BeanCreationException bce = (BeanCreationException) rootCause;
                            String bceBeanName = bce.getBeanName();
                            if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Skipping advisor '" + name +
                                            "' with dependency on currently created bean: " + ex.getMessage());
                                }
                                // Ignore: indicates a reference back to the bean we're trying to advise.
                                // We want to find advisors other than the currently created bean itself.
                                continue;
                            }
                        }
                        throw ex;
                    }
                }
            }
        }
        return advisors;
    }

  進入到isEligibleBean(name)方法:

   進入isEligibleAdvisorBean(beanName)方法:

protected boolean isEligibleAdvisorBean(String beanName) {
        /**
         * 容器中包含了這個Bean定義,並且Bean定義的角色為BeanDefinition.ROLE_INFRASTRUCTURE
         */
        return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
                this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
    }

  如果是合適的就儲存在advisors中並返回;至此findCandidateAdvisors()執行完畢!!!

  ② 找到的增強器是否能作用在當前的類上,findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)方法:

   進入到AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)方法:

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        //若候選的增強器集合為空直接返回
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        //定義一個合適的增強器集合物件
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        //迴圈我們候選的增強器物件
        for (Advisor candidate : candidateAdvisors) {
            //判斷我們的增強器物件是不是實現了IntroductionAdvisor (很明顯我們事務的沒有實現 所以不會走下面的邏輯)
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        //不為空
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            //判斷我們的增強器物件是不是實現了IntroductionAdvisor (很明顯我們事務的沒有實現 所以不會走下面的邏輯)
            if (candidate instanceof IntroductionAdvisor) {
                //在上面已經處理過 ,不需要處理
                continue;
            }
            /**
             * 真正的判斷增強器是否合適當前類
             */
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

  真正的判斷增強器是否合適當前類,canApply(candidate, clazz, hasIntroductions)方法:

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        //判斷我們的增強器 IntroductionAdvisor
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        //判斷我們事務的增強器BeanFactoryTransactionAttributeSourceAdvisor是否實現了PointcutAdvisor
        else if (advisor instanceof PointcutAdvisor) {
            //轉為PointcutAdvisor型別
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            //找到真正能用的增強器
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            return true;
        }
    }

  找到真正能用的增強器,canApply(pca.getPointcut(), targetClass, hasIntroductions)方法:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }
        /**
         * 通過切點獲取到一個方法匹配器物件
         */
        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        //判斷匹配器是不是IntroductionAwareMethodMatcher
        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        //建立一個集合用於儲存targetClass的class物件
        Set<Class<?>> classes = new LinkedHashSet<>();
        //判斷當前class是不是代理的class物件
        if (!Proxy.isProxyClass(targetClass)) {
            //加入到集合中去
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        //獲取到targetClass所實現的介面的class物件,然後加入到集合中
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        //迴圈所有的class物件
        for (Class<?> clazz : classes) {
            //通過class獲取到所有的方法
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            //迴圈我們的方法
            for (Method method : methods) {
                //通過methodMatcher.matches來匹配我們的方法
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        //通過方法匹配器進行匹配
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }
        return false;
    }

  進入methodMatcher.matches(method, targetClass)方法:

public boolean matches(Method method, @Nullable Class<?> targetClass) {
        if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
            return false;
        }
        /**
         * 獲取我們@EnableTransactionManagement註解為我們容器中匯入的ProxyTransactionManagementConfiguration
         * 配置類中的TransactionAttributeSource物件
         */
        TransactionAttributeSource tas = getTransactionAttributeSource();
        //若事務屬性原為null或者 解析出來的事務註解屬性不為空    表示方法匹配
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }

  進入到獲取事務註解屬性tas.getTransactionAttribute(method, targetClass)方法:

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        //判斷method所在的class 是不是Object型別
        if (method.getDeclaringClass() == Object.class) {
            return null;
        }

        //構建我們的快取key
        Object cacheKey = getCacheKey(method, targetClass);
        //先去我們的快取中獲取
        TransactionAttribute cached = this.attributeCache.get(cacheKey);
        //快取中不為空
        if (cached != null) {
            //判斷快取中的物件是不是空事務屬性的物件
            if (cached == NULL_TRANSACTION_ATTRIBUTE) {
                return null;
            }
            else {
                return cached;
            }
        }
        else {
            //查詢我們的事務註解
            TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
            //若解析出來的事務註解屬性為空
            if (txAttr == null) {
                //往快取中存放空事務註解屬性
                this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
            }
            else {
                //我們執行方法的描述符 包名+類名+方法名
                String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
                //把方法描述設定到事務屬性上去
                if (txAttr instanceof DefaultTransactionAttribute) {
                    ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
                }
                //加入到快取
                this.attributeCache.put(cacheKey, txAttr);
            }
            return txAttr;
        }
    }

  進入查詢我們的事務註解,computeTransactionAttribute(method, targetClass)方法:

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        //判斷我們的事務方法上的修飾符是不是public的
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        }

        // The method may be on an interface, but we need attributes from the target class.
        // If the target class is null, the method will be unchanged.
        Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

        //第一:先去目標物件的方法上去找我們的事務註解
        TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
        if (txAttr != null) {
            return txAttr;
        }

        //第二:去目標物件上找事務註解
        txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }

        if (specificMethod != method) {
            //第三:去我們的實現類的介面上的方法去找事務註解
            txAttr = findTransactionAttribute(method);
            if (txAttr != null) {
                return txAttr;
            }
            //第四:去我們的實現類的介面上去找事務註解
            txAttr = findTransactionAttribute(method.getDeclaringClass());
            if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                return txAttr;
            }
        }

        return null;
    }

  進入到找@Transactional註解,findTransactionAttribute(specificMethod)方法:

   進入determineTransactionAttribute(method)方法:

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
        //獲取我們的註解解析器
        for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
            //通過註解解析器去解析我們的元素(方法或者類)上的註解
            TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
            if (attr != null) {
                return attr;
            }
        }
        return null;
    }

  進入annotationParser.parseTransactionAnnotation(element)方法:

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
        //從element物件中獲取@Transactional註解 然後把註解屬性封裝到了AnnotationAttributes
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                element, Transactional.class, false, false);
        if (attributes != null) {
            //解析出真正的事務屬性物件
            return parseTransactionAnnotation(attributes);
        }
        else {
            return null;
        }
    }

  進入到解析出真正的事務屬性物件,parseTransactionAnnotation(attributes)方法:

protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
        //建立一個基礎規則的事務屬性物件
        RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
        //解析@Transactionl上的傳播行為
        Propagation propagation = attributes.getEnum("propagation");
        rbta.setPropagationBehavior(propagation.value());
        //解析@Transactionl上的隔離級別
        Isolation isolation = attributes.getEnum("isolation");
        rbta.setIsolationLevel(isolation.value());
        //解析@Transactionl上的事務超時事件
        rbta.setTimeout(attributes.getNumber("timeout").intValue());
        rbta.setReadOnly(attributes.getBoolean("readOnly"));
        //解析@Transactionl上的事務管理器的名稱
        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;
    }

   至此computeTransactionAttribute(method, targetClass)方法執行完畢!!!

   然後把我們執行方法的描述符設定到TransactionAttribute事務屬性中,表示該方法需要執行Spring事務,並把事務註解屬性加入到快取attributeCache中,至此獲取事務註解屬性tas.getTransactionAttribute完畢!!!

  如果canApply方法返回true表示找到真正能用的增強器了,然後就把合適的增強器加入到eligibleAdvisors中:

   至此findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)執行完畢!!!

   ③ extendAdvisors(eligibleAdvisors) 擴充套件增強器

   ④ sortAdvisors(eligibleAdvisors) 排序

  其中③,④ 略 具體參考Spring系列(五):Spring AOP原始碼解析,其實事務找增強器相對Aop簡單很多,到此findEligibleAdvisors(beanClass, beanName)執行完畢!!!

   到此Spring事務建立代理物件完畢!!!

 四、Spring事務代理呼叫過程

   第一步:執行addUser(user)方法

  其實就是呼叫org.springframework.aop.framework.JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        //獲取到我們的目標物件
        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            //若是equals方法不需要代理
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            //若是hashCode方法不需要代理
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            //若是DecoratingProxy也不要攔截器執行
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            /**
             * 這個配置是暴露我們的代理物件到執行緒變數中,需要搭配@EnableAspectJAutoProxy(exposeProxy = true)一起使用
        * 比如在目標物件方法中再次獲取代理物件可以使用這個AopContext.currentProxy()
             * 還有的就是事務方法呼叫事務方法的時候也是用到這個
             */
            if (this.advised.exposeProxy) {
                //把我們的代理物件暴露到執行緒變數中
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            //獲取我們的目標物件
            target = targetSource.getTarget();
            //獲取我們目標物件的class
            Class<?> targetClass = (target != null ? target.getClass() : null);

            //把aop的advisor轉化為攔截器鏈
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            //如果攔截器鏈為空
            if (chain.isEmpty()) {
                //通過反射直接呼叫執行
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                //建立一個方法呼叫物件
                MethodInvocation invocation =
                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                //呼叫執行
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

   進入到invocation.proceed()方法,該方法的呼叫用到了遞迴和責任鏈設計模式:

public Object proceed() throws Throwable {
        //從-1開始,下標=攔截器的長度-1的條件滿足表示執行到了最後一個攔截器的時候,此時執行目標方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        //獲取第一個方法攔截器使用的是前++
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

  進入到((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法:

public Object invoke(MethodInvocation invocation) throws Throwable {
        //獲取我們的代理物件的class屬性
        Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
        /**
         * 以事務的方式呼叫目標方法
         * 在這埋了一個鉤子函式 用來回調目標方法的
         */
        return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
    }

  呼叫invokeWithinTransaction方法

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
            final InvocationCallback invocation) throws Throwable {

        //獲取我們的事務屬源物件
        TransactionAttributeSource tas = getTransactionAttributeSource();
        //通過事務屬性源物件獲取到我們的事務屬性資訊
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        //獲取我們配置的事務管理器物件
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        //從tx屬性物件中獲取出標註了@Transactionl的方法描述符
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

        //處理宣告式事務
        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            //有沒有必要建立事務
            TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

            Object retVal;
            try {
                //呼叫鉤子函式進行回撥目標方法
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                //丟擲異常進行回滾處理
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                //清空我們的執行緒變數中transactionInfo的值
                cleanupTransactionInfo(txInfo);
            }
            //提交事務
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }
        //程式設計式事務
        else {
            final ThrowableHolder throwableHolder = new ThrowableHolder();

            // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
            try {
                Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
                    TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                    try {
                        return invocation.proceedWithInvocation();
                    }
                    catch (Throwable ex) {
                        if (txAttr.rollbackOn(ex)) {
                            // A RuntimeException: will lead to a rollback.
                            if (ex instanceof RuntimeException) {
                                throw (RuntimeException) ex;
                            }
                            else {
                                throw new ThrowableHolderException(ex);
                            }
                        }
                        else {
                            // A normal return value: will lead to a commit.
                            throwableHolder.throwable = ex;
                            return null;
                        }
                    }
                    finally {
                        cleanupTransactionInfo(txInfo);
                    }
                });

                // Check result state: It might indicate a Throwable to rethrow.
                if (throwableHolder.throwable != null) {
                    throw throwableHolder.throwable;
                }
                return result;
            }
            catch (ThrowableHolderException ex) {
                throw ex.getCause();
            }
            catch (TransactionSystemException ex2) {
                if (throwableHolder.throwable != null) {
                    logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                    ex2.initApplicationException(throwableHolder.throwable);
                }
                throw ex2;
            }
            catch (Throwable ex2) {
                if (throwableHolder.throwable != null) {
                    logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                }
                throw ex2;
            }
        }
    }

  1 createTransactionIfNecessary(tm, txAttr, joinpointIdentification)方法:

protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
            @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

        // 把我們的方法描述符作為一個事務名稱
        if (txAttr != null && txAttr.getName() == null) {
            txAttr = new DelegatingTransactionAttribute(txAttr) {
                @Override
                public String getName() {
                    return joinpointIdentification;
                }
            };
        }

        TransactionStatus status = null;
        if (txAttr != null) {
            if (tm != null) {
                //獲取一個事務狀態
                status = tm.getTransaction(txAttr);
            }
            else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
                            "] because no transaction manager has been configured");
                }
            }
        }
        //把事務狀態和事務屬性等資訊封裝成一個TransactionInfo物件
        return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
    }
  1.1 進入獲取一個事務狀態,tm.getTransaction(txAttr)方法:
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
        //嘗試獲取一個事務物件
        Object transaction = doGetTransaction();

        // Cache debug flag to avoid repeated checks.
        boolean debugEnabled = logger.isDebugEnabled();

        /**
         * 判斷從上一個方法傳遞進來的事務屬性是不是為空
         */
        if (definition == null) {
            //為空的話,執行非事務方法
            definition = new DefaultTransactionDefinition();
        }

        /**
         * 判斷是不是已經存在了事務物件
         */
        if (isExistingTransaction(transaction)) {
            //處理存在的事務
            return handleExistingTransaction(definition, transaction, debugEnabled);
        }

        //檢查事務設定的超時時間
        if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
            throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
        }

        /**
         * 若當前的事務屬性式 PROPAGATION_MANDATORY 表示必須執行在事務中,若當前沒有事務就丟擲異常
         * 由於isExistingTransaction(transaction)跳過了這裡,說明當前是不存在事務的,那麼就會丟擲異常
         */
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException(
                    "No existing transaction found for transaction marked with propagation 'mandatory'");
        }
        /**
         * PROPAGATION_REQUIRED 當前存在事務就加入到當前的事務,沒有就新開一個
         * PROPAGATION_REQUIRES_NEW:新開一個事務,若當前存在事務就掛起當前事務
         * PROPAGATION_NESTED: PROPAGATION_NESTED
            表示如果當前正有一個事務在執行中,則該方法應該執行在 一個巢狀的事務中,
            被巢狀的事務可以獨立於封裝事務進行提交或者回滾(儲存點),
            如果封裝事務不存在,行為就像 PROPAGATION_REQUIRES_NEW
         */
        else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            /**
             * 掛起當前事務,在這裡為啥傳入null?
             * 因為邏輯走到這裡了,經過了上面的isExistingTransaction(transaction) 判斷當前是不存在事務的
             * 所有再這裡是掛起當前事務傳遞一個null進去
             */
            SuspendedResourcesHolder suspendedResources = suspend(null);
            if (debugEnabled) {
                logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
            }
            try {
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                //新建立一個事務狀態
                DefaultTransactionStatus status = newTransactionStatus(
                        definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                //開啟一個新的事物
                doBegin(transaction, definition);
                //把當前的事務資訊繫結到執行緒變數去
                prepareSynchronization(status, definition);
                return status;
            }
            catch (RuntimeException | Error ex) {
                resume(null, suspendedResources);
                throw ex;
            }
        }
        else { //建立一個空的事務
            // Create "empty" transaction: no actual transaction, but potentially synchronization.
            if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
                logger.warn("Custom isolation level specified but no actual transaction initiated; " +
                        "isolation level will effectively be ignored: " + definition);
            }
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
        }
    }

  ① 進入到doGetTransaction()方法:

protected Object doGetTransaction() {
        //建立一個數據源事務物件
        DataSourceTransactionObject txObject = new DataSourceTransactionObject();
        //是否允許當前事務設定保持點
        txObject.setSavepointAllowed(isNestedTransactionAllowed());
        /**
         * TransactionSynchronizationManager 事務同步管理器物件(該類中都是區域性執行緒變數)
         * 用來儲存當前事務的資訊,我們第一次從這裡去執行緒變數中獲取 事務連線持有器物件 通過資料來源為key去獲取
         * 由於第一次進來開始事務 我們的事務同步管理器中沒有被存放.所以此時獲取出來的conHolder為null
         */
        ConnectionHolder conHolder =
                (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
        txObject.setConnectionHolder(conHolder, false);
        //返回事務物件
        return txObject;
    }

  ② 進入isExistingTransaction(transaction)方法:

protected boolean isExistingTransaction(Object transaction) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        //若第一次進來開始事務,txObject.hasConnectionHolder() 返回的null 那麼表示不存在事務
        return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
    }

  ③ 由於事務傳播機制是TransactionDefinition.PROPAGATION_REQUIRED,所以走下面分支

 

   ④ 進入掛起事務,suspend(null)方法:

protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
        //判斷當前的執行緒變數中 有沒有啟用的事物,有需要清空執行緒變數
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
            try {
                Object suspendedResources = null;
                if (transaction != null) {
                    suspendedResources = doSuspend(transaction);
                }
                //獲取已存在的事務的名稱
                String name = TransactionSynchronizationManager.getCurrentTransactionName();
                //清空執行緒變數的
                TransactionSynchronizationManager.setCurrentTransactionName(null);
                //獲取出只讀事務的名稱
                boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
                //清空執行緒變數的
                TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
                //獲取已存在事務的隔離級別
                Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                //清空隔離級別
                TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
                //獲取啟用標誌
                boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
                //清空標記
                TransactionSynchronizationManager.setActualTransactionActive(false);
                //把上訴從執行緒變數中獲取出來的存在事務屬性封裝為掛起的事務屬性返回出去
                return new SuspendedResourcesHolder(
                        suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
            }
            catch (RuntimeException | Error ex) {
                // doSuspend failed - original transaction is still active...
                doResumeSynchronization(suspendedSynchronizations);
                throw ex;
            }
        }
        else if (transaction != null) {
            // Transaction active but no synchronization active.
            Object suspendedResources = doSuspend(transaction);
            return new SuspendedResourcesHolder(suspendedResources);
        }
        else {
            // Neither transaction nor synchronization active.
            return null;
        }
    }

  ⑤ 進入到事務開始,doBegin(transaction, definition)方法:

protected void doBegin(Object transaction, TransactionDefinition definition) {
        //強制轉化事務物件
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;

        try {
            //判斷事務物件沒有資料庫連線持有器
            if (!txObject.hasConnectionHolder() ||
                    txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                //通過資料來源獲取一個數據庫連線物件
                Connection newCon = obtainDataSource().getConnection();
                if (logger.isDebugEnabled()) {
                    logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                }
                //把我們的資料庫連線包裝成一個ConnectionHolder物件 然後設定到我們的txObject物件中去
                txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }

            //標記當前的連線是一個同步事務
            txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
            con = txObject.getConnectionHolder().getConnection();

            //為當前的事務設定隔離級別
            Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
            txObject.setPreviousIsolationLevel(previousIsolationLevel);

            //關閉自動提交
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false);
            }

            //判斷事務為只讀事務
            prepareTransactionalConnection(con, definition);
            //設定事務啟用
            txObject.getConnectionHolder().setTransactionActive(true);

            //設定事務超時時間
            int timeout = determineTimeout(definition);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }

            // 繫結我們的資料來源和連線到我們的同步管理器上   把資料來源作為key,資料庫連線作為value 設定到執行緒變數中
            if (txObject.isNewConnectionHolder()) {
                TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
            }
        }

        catch (Throwable ex) {
            if (txObject.isNewConnectionHolder()) {
                //釋放資料庫連線
                DataSourceUtils.releaseConnection(con, obtainDataSource());
                txObject.setConnectionHolder(null, false);
            }
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }

  ⑥ 進入到prepareSynchronization(status, definition)方法:

protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
        if (status.isNewSynchronization()) {
            //繫結事務啟用
            TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
            //當前事務的隔離級別
            TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
                    definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
                            definition.getIsolationLevel() : null);
            //是否為只讀事務
            TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
            //事務的名稱
            TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
            TransactionSynchronizationManager.initSynchronization();
        }
    }
  1.2 把事務狀態和事務屬性等資訊封裝成一個TransactionInfo物件,prepareTransactionInfo(tm, txAttr, joinpointIdentification, status)方法:
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
            TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {

        TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
        if (txAttr != null) {
            // We need a transaction for this method...
            if (logger.isTraceEnabled()) {
                logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
            }
            // The transaction manager will flag an error if an incompatible tx already exists.
            txInfo.newTransactionStatus(status);
        }
        else {
            // The TransactionInfo.hasTransaction() method will return false. We created it only
            // to preserve the integrity of the ThreadLocal stack maintained in this class.
            if (logger.isTraceEnabled())
                logger.trace("Don't need to create transaction for [" + joinpointIdentification +
                        "]: This method isn't transactional.");
        }

        // We always bind the TransactionInfo to the thread, even if we didn't create
        // a new transaction here. This guarantees that the TransactionInfo stack
        // will be managed correctly even if no transaction was created by this aspect.
        txInfo.bindToThread();
        return txInfo;
    }

  2 呼叫鉤子函式進行回撥目標方法,invocation.proceedWithInvocation()方法最終會呼叫到目標方法裡面:

   第二步:addLog("新增使用者") 其中事務註解上的傳播機制是propagation = Propagation.NESTED

   執行流程參考前面的addUser流程,區別是到AbstractPlatformTransactionManager#getTransaction裡面的isExistingTransaction (transaction),這個時候是返回true的,所以執行handleExistingTransaction(definition, transaction, debugEnabled)方法:

private TransactionStatus handleExistingTransaction(
            TransactionDefinition definition, Object transaction, boolean debugEnabled)
            throws TransactionException {

        /**
         * 判斷當前的事務行為是不是PROPAGATION_NEVER的
         * 表示為不支援事務,但是當前又存在一個事務,所以丟擲異常
         */
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
            throw new IllegalTransactionStateException(
                    "Existing transaction found for transaction marked with propagation 'never'");
        }

        /**
         * 判斷當前的事務屬性不支援事務,PROPAGATION_NOT_SUPPORTED,所以需要先掛起已經存在的事務
         */
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
            if (debugEnabled) {
                logger.debug("Suspending current transaction");
            }
            //掛起存在的事務
            Object suspendedResources = suspend(transaction);
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            //建立一個新的非事務狀態(儲存了上一個存在事務狀態的屬性)
            return prepareTransactionStatus(
                    definition, null, false, newSynchronization, debugEnabled, suspendedResources);
        }

        /**
         * 當前的事務屬性狀態是PROPAGATION_REQUIRES_NEW表示需要新開啟一個事務狀態
         */
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
            if (debugEnabled) {
                logger.debug("Suspending current transaction, creating new transaction with name [" +
                        definition.getName() + "]");
            }
            //掛起已經存在的事務
            SuspendedResourcesHolder suspendedResources = suspend(transaction);
            try {
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                //建立一個新的事務狀態(包含了掛起的事務的屬性)
                DefaultTransactionStatus status = newTransactionStatus(
                        definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                //開啟新的事務
                doBegin(transaction, definition);
                //把新的事務狀態設定到當前的執行緒變數中去
                prepareSynchronization(status, definition);
                return status;
            }
            catch (RuntimeException | Error beginEx) {
                resumeAfterBeginException(transaction, suspendedResources, beginEx);
                throw beginEx;
            }
        }

        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            if (!isNestedTransactionAllowed()) {
                throw new NestedTransactionNotSupportedException(
                        "Transaction manager does not allow nested transactions by default - " +
                        "specify 'nestedTransactionAllowed' property with value 'true'");
            }
            if (debugEnabled) {
                logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
            }
            //巢狀事務的處理
            if (useSavepointForNestedTransaction()) {
                //開啟一個新的事務
                DefaultTransactionStatus status =
                        prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
                //為事務設定一個回退點
                status.createAndHoldSavepoint();
                return status;
            }
            else {// Nested transaction through nested begin and commit/rollback calls.
                // Usually only for JTA: Spring synchronization might get activated here
                // in case of a pre-existing JTA transaction.
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                DefaultTransactionStatus status = newTransactionStatus(
                        definition, transaction, true, newSynchronization, debugEnabled, null);
                doBegin(transaction, definition);
                prepareSynchronization(status, definition);
                return status;
            }
        }

        // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
        if (debugEnabled) {
            logger.debug("Participating in existing transaction");
        }
        if (isValidateExistingTransaction()) {
            if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
                Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
                    Constants isoConstants = DefaultTransactionDefinition.constants;
                    throw new IllegalTransactionStateException("Participating transaction with definition [" +
                            definition + "] specifies isolation level which is incompatible with existing transaction: " +
                            (currentIsolationLevel != null ?
                                    isoConstants.toCode(currentIsolationLevel, DefaultTr