1. 程式人生 > >Spring事務原始碼分析

Spring事務原始碼分析

事務屬性定義介面

TransactionDefinition是事務屬性定義介面,儲存事務定義的各種屬性,如超時時間、隔離級別、傳播屬性等。

public interface TransactionDefinition {
    //獲取事務傳播型別
    int getPropagationBehavior();

    //獲取事務隔離級別
    int getIsolationLevel();

    //獲取事務超時時間
    int getTimeout();

    //事務的只讀性
    boolean isReadOnly();

    //獲取事務名稱
    String getName();

}

事務例項介面

TransactionStatus是事務例項介面,表示了當前事務在記憶體中的一個例項,從名字來看儲存了事務的執行狀態資訊。
AbstractTransactionStatus是抽象實現,DefaultTransactionStatus是事務例項的預設實現。

事務管理器

PlatformTransactionManager是Spring事務的核心介面,一般不會直接使用該介面,應用程式可以直接用TransactionTemplate或者AOP進行事務操作。AbstractPlatformTransactionManager是PlatformTransactionManager的抽象類實現。

public interface PlatformTransactionManager {

    //根據事務指定的策略獲取啟用的事務或者重新建立一個事務。
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

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

    //回滾事務
    void rollback(TransactionStatus status) throws
TransactionException; }

AbstractPlatformTransactionManager定義事務實現的骨架。

獲取事務

getTransaction(TransactionDefinition definition)主要邏輯是首先獲取當前執行緒的事務:

        Object transaction = doGetTransaction();

注意doGetTransaction是個鉤子方法,負責子類方法的回撥,凡是以do開頭的方法都類似,後續不在贅述。

如果當前執行緒已經存在事務,則handleExistingTransaction(definition, transaction, debugEnabled),這個方法根據配置的事務策略處理存在的事務:

        if (isExistingTransaction(transaction)) {
            // Existing transaction found -> check propagation behavior to find out how to behave.
            return handleExistingTransaction(definition, transaction, debugEnabled);
        }

如果當前執行緒不存在事務,則開啟新事務:

else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            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 ex) {
                resume(null, suspendedResources);
                throw ex;
            }
            catch (Error err) {
                resume(null, suspendedResources);
                throw err;
            }

我們選擇DataSourceTransactionManager的doBegin看看,裡面設定事務為手動提交模式,然後啟用當前事務:

// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
            // so we don't want to do it unnecessarily (for example if we've explicitly
            // configured the connection pool to set it already).
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false); //設定為手動提交
            }
            txObject.getConnectionHolder().setTransactionActive(true);

事務提交

主要實現方法是processCommit,在事務提交之前還做了其他額外準備操作,然後執行doCommit方法,出錯時不會進行資源清理操作,不做回滾操作,回滾操作由呼叫者發起。

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        try {
            boolean beforeCompletionInvoked = false;
            try {
                prepareForCommit(status);
                triggerBeforeCommit(status);
                triggerBeforeCompletion(status);
                beforeCompletionInvoked = true;
                boolean globalRollbackOnly = false;
                if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
                    globalRollbackOnly = status.isGlobalRollbackOnly();
                }
                if (status.hasSavepoint()) {
                    if (status.isDebug()) {
                        logger.debug("Releasing transaction savepoint");
                    }
                    status.releaseHeldSavepoint();
                }
                else if (status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction commit");
                    }
                    doCommit(status);
                }
                // Throw UnexpectedRollbackException if we have a global rollback-only
                // marker but still didn't get a corresponding exception from commit.
                if (globalRollbackOnly) {
                    throw new UnexpectedRollbackException(
                            "Transaction silently rolled back because it has been marked as rollback-only");
                }
            }
            catch (UnexpectedRollbackException ex) {
                // can only be caused by doCommit
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
                throw ex;
            }

            ...

事務回滾

    public final void rollback(TransactionStatus status) throws TransactionException {
        if (status.isCompleted()) {
            throw new IllegalTransactionStateException(
                    "Transaction is already completed - do not call commit or rollback more than once per transaction");
        }

        DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
        processRollback(defStatus);
    }

事務同步管理器

TransactionSynchronizationManager關鍵實現是依賴ThreadLocal。各種資料庫資源儲存在各自執行緒的副本中,保證執行緒安全,典型的用空間換時間的做法。

    private static final ThreadLocal<Map<Object, Object>> resources =
            new NamedThreadLocal<Map<Object, Object>>("Transactional resources");

    private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
            new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");

    private static final ThreadLocal<String> currentTransactionName =
            new NamedThreadLocal<String>("Current transaction name");

    private static final ThreadLocal<Boolean> currentTransactionReadOnly =
            new NamedThreadLocal<Boolean>("Current transaction read-only status");

    private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
            new NamedThreadLocal<Integer>("Current transaction isolation level");

    private static final ThreadLocal<Boolean> actualTransactionActive =
            new NamedThreadLocal<Boolean>("Actual transaction active");

相關推薦

Spring事務原始碼分析

事務屬性定義介面 TransactionDefinition是事務屬性定義介面,儲存事務定義的各種屬性,如超時時間、隔離級別、傳播屬性等。 public interface TransactionDefinition { //獲取事務傳播型別

Spring事務原始碼分析專題(一)JdbcTemplate使用及原始碼分析

Spring中的資料訪問,JdbcTemplate使用及原始碼分析 # 前言 本系列文章為事務專欄分析文章,整個事務分析專題將按下面這張圖完成 ![image-20200718220712800](https://gitee.com/wx_cc347be696/blogImage/raw/master

【筆記】Spring 事務原理分析原始碼剖析

概述 事務處理是一個重要並且涉及範圍很廣的領域,涉及到併發和資料一致性方面的問題。作為應用平臺的 Spring 具有在多種環境中配置和使用事務處理的能力,也就是說通過使用 Spring 的事務處理,可以把事務處理的工作統一起來,為事務處理提供統一支援。 由於這

Spring 宣告式事務原始碼分析

Spring 的宣告式事務實現方式主要有2種,一種為通過使用Spring的< tx:advice >定義事務通知與AOP相關配置實現,另為一種通過@Transactional實現事務管理實現,個人認為本質上其實都一樣,就是用定義的註解或者配置資訊將目

Spring AOP原始碼分析

概述 定義 官方定義:Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about prog

Spring IOC原始碼分析

Spring IOC原始碼分析 Spring 應用 1 注入巢狀Bean 在Spring中,如果某個Bean所依賴的Bean不想被Spring容器直接訪問,可以使用巢狀Bean。和普通的Bean一樣,使用元素來定義巢狀的Bean,巢狀Bean只對它的外部的Bean有效,Sprin

Spring-AOP原始碼分析

一、概述 Spring的兩大特性:IOC和AOP。 AOP是面向切面程式設計,Spring內建了自己實現的基於動態代理技術的AOP,同時還支援成熟的AspectJ框架,我們這裡主要講述的還是內建的基於動態代理的AOP實現。因為面對一些普通的需求,Spring內建的AOP已經綽綽有餘。

關於spring事務原始碼的一些小理解

1、spring事務的簡單概述 由於實現事務功能的方式各不相同,Spring進行了統一的抽象,形成了PlatformTransactionManager事務管理器頂級介面(平臺事務管理器),事務的提交、回滾等操作全部交給它來實現 先來看下三大介面 PlatformTransactionManage

Spring Ioc 原始碼分析之Bean的載入和構造

我們都知道,Spring Ioc和Aop是Spring的核心的功能,因此花一點時間去研究還是很有意義的,如果僅僅是知其所以然,也就體會不到大師設計Spring的精華,還記得那句話,Spring為JavaEE開發帶來了春天。IOC就是Inversion of control 也就是控制反轉的意思,另一種稱呼叫做

Spring-BeanFactory原始碼分析(一)

前言 Spring 版本:5.0.9.RELEASE 正式進入Spring 原始碼分析這個模組了,對於spring這個龐大的工程,如果要一點點的完全分析是非常困難的,對於應用型框架,我還是偏向於掌握思想或者設計,而不是記住程式碼,對於初次看spring原始

Spring Cloud原始碼分析之Eureka篇第六章:服務註冊

在文章《Spring Cloud原始碼分析之Eureka篇第四章:服務註冊是如何發起的 》的分析中,我們知道了作為Eureka Client的應用啟動時,在com.netflix.discovery.DiscoveryClient類的initScheduledT

Spring MVC原始碼分析(一)

一、Servlet Spring MVC中核心Servlet(DispatcherServlet)的繼承結構 圖示(C)表示是類,而圖示(I)表示介面       而上圖的其中HttpServlet、GenericServlet、Servlet、ServletConfi

【轉】Spring AMQP 原始碼分析 05

### 準備 ## 目標 瞭解 Spring AMQP Message Listener 如何處理異常 ## 前置知識 《Spring AMQP 原始碼分析 04 - MessageListener》 ## 相關資源 原始碼版本:Spring AMQP

【轉】Spring AMQP 原始碼分析 04

### 準備 ## 目標 瞭解 Spring AMQP 如何實現非同步訊息投遞(推模式) ## 前置知識 《RabbitMQ入門_05_多執行緒消費同一佇列》 ## 相關資源 原始碼版本:Spring AMQP 1.7.3.RELEASE ## 測試

【轉】Spring AMQP 原始碼分析 03

### 準備 ## 目標 瞭解 Spring AMQP 訊息轉化實現 ## 相關資源 ## 測試程式碼 gordon.study.rabbitmq.springamqp.JsonMessage.java   ### 分析 ## Mes

Spring Cloud原始碼分析之Eureka篇第八章:服務註冊名稱的來歷

關於服務註冊名稱 服務註冊名稱,是指Eureka client註冊到Eureka server時,用於標記自己身份的標誌,舉例說明,以下是個簡單的Eureka client配置: server: port: 8082 spring: applicatio

Spring Boot 原始碼分析

Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。通過這種方式,Boot致力於在蓬勃發展的快速應用開發領域(rapid application d

Spring事務原始碼梳理

通過註解@EnableTransactionManagement中的@Import(TransactionManagementConfigurationSelector.class)給容器中匯入了兩個元件,分別是:AutoProxyRegistrar和ProxyTransactionManagement

spring--aop_2_原始碼分析之MethodInterceptor

前提: 前兩篇分析了aop 兩種方式實現的大致流程和方式,在這兩種實現方式中都有一個很重要的方法獲取攔截器鏈 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionA

spring原始碼分析 一 從ContextLoaderListener開始·

原始碼環境 : idea + spring 4.3.4 +tomcat7 + gradle附 : 基於 java  註解的 配置元資料 的 web.xml 配置做參考(spring 3.0 後支援)<?xml version="1.0" encoding="UTF-8"