1. 程式人生 > >Spring技術內幕——DataSourceTransactionManager

Spring技術內幕——DataSourceTransactionManager

Spring的事務處理中,通用的事務處理流程框架是由抽象事務管理器AbstractPlatformTransactionManager來提供的,而具體的底層事務處理實現,由PlatformTransactionManager的具體實現類來實現,如 DataSourceTransactionManager 、JtaTransactionManager和 HibernateTransactionManager等。

對於具體的事務管理器而言,它們只需要處理和具體資料來源相關的元件設定就可以了。如doGetTransaction(),doCommit(status)方法等。

本文主要介紹DataSourceTransactionManager中的具體實現。

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager  
        implements ResourceTransactionManager, InitializingBean {  
    //注入資料來源  
    private DataSource dataSource;  
//資料來源事務處理器預設構造方法,建立一個數據源事務處理器例項,並設定允許巢狀事務  
    public DataSourceTransactionManager() {  
        setNestedTransactionAllowed(true);  
    }  
    //根據給定資料來源,建立一個數據源事務處理器例項  
    public DataSourceTransactionManager(DataSource dataSource) {  
        this();  
        setDataSource(dataSource);  
        afterPropertiesSet();  
    }  
    //設定資料來源  
    public void setDataSource(DataSource dataSource) {  
        if (dataSource instanceof TransactionAwareDataSourceProxy) {  
            //如果資料來源是一個事務包裝資料來源代理,則獲取事務包裝代理的目標資料來源   
            this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();  
        }  
        else {  
            this.dataSource = dataSource;  
        }  
    }  
    //獲取資料來源  
    public DataSource getDataSource() {  
        return this.dataSource;  
    }  
    //資料來源事務處理器物件構造方法的回撥函式  
    public void afterPropertiesSet() {  
        if (getDataSource() == null) {  
            throw new IllegalArgumentException("Property 'dataSource' is required");  
        }  
    }  
public Object getResourceFactory() {  
        return getDataSource();  
    }  
//建立事務,對資料庫而言,是由Connection來完成事務工作的。該方法把資料庫的//Connection物件放到一個ConnectionHolder物件中,然後封裝到一個  
//DataSourceTransactionObject物件中  
    protected Object doGetTransaction() {  
        //建立資料來源事務物件  
        DataSourceTransactionObject txObject = new DataSourceTransactionObject();  
        //設定資料來源事務物件對巢狀事務使用儲存點  
        txObject.setSavepointAllowed(isNestedTransactionAllowed());  
        //從事務管理容器中獲取存放資料庫Connection的物件  
        ConnectionHolder conHolder =  
            (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);  
        txObject.setConnectionHolder(conHolder, false);  
        return txObject;  
    }  
    //判斷是否已經存在事務  
    protected boolean isExistingTransaction(Object transaction) {  
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;  
    //根據存放資料庫連線的ConnectionHolder的isTransactionActive屬性來判斷  
        return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());  
    }  
    //處理事務開始的方法  
    protected void doBegin(Object transaction, TransactionDefinition definition) {  
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;  
        Connection con = null;  
        try {  
            //如果資料來源事務物件的ConnectionHolder為null或者是事務同步的  
            if (txObject.getConnectionHolder() == null ||  
        txObject.getConnectionHolder().isSynchronizedWithTransaction()) {  
                //獲取當前資料來源的資料庫連線  
                Connection newCon = this.dataSource.getConnection();  
                if (logger.isDebugEnabled()) {  
                    logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");  
                }  
                //為資料來源事務物件設定ConnectionHolder  
                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");  
                }  
                //設定資料庫連線自動事務提交屬性為false,即禁止自動事務提交  
                con.setAutoCommit(false);  
            }  
            //啟用當前資料來源事務物件的事務配置  
            txObject.getConnectionHolder().setTransactionActive(true);  
            //獲取事務配置的超時時長  
int timeout = determineTimeout(definition);  
//如果事務配置的超時時長不等於事務的預設超時時長  
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {  
        //資料來源事務物件設定超時時長  
        txObject.getConnectionHolder().setTimeoutInSeconds(timeout);  
            }  
            //把當前資料庫Connection和執行緒繫結  
            if (txObject.isNewConnectionHolder()) {  
        TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());  
            }  
        }  
        catch (Exception ex) {  
            DataSourceUtils.releaseConnection(con, this.dataSource);  
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);  
        }  
    }  
    //事務掛起  
    protected Object doSuspend(Object transaction) {  
        //獲取事務物件  
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;  
        //將事務物件中的ConnectionHolders設定為null  
        txObject.setConnectionHolder(null);  
        ConnectionHolder conHolder = (ConnectionHolder)  
        //解除事務物件和當前執行緒的繫結    TransactionSynchronizationManager.unbindResource(this.dataSource);  
        return conHolder;  
    }  
    //事務恢復  
    protected void doResume(Object transaction, Object suspendedResources) {  
        //獲取已暫停事務的ConnectionHolder  
        ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;  
        //重新將事務物件和當前執行緒繫結  
        TransactionSynchronizationManager.bindResource(this.dataSource, conHolder);  
    }  
    //事務提交  
    protected void doCommit(DefaultTransactionStatus status) {  
        //獲取事務物件  
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();  
        //通過事務物件獲取資料庫連線  
        Connection con = txObject.getConnectionHolder().getConnection();  
        if (status.isDebug()) {  
            logger.debug("Committing JDBC transaction on Connection [" + con + "]");  
        }  
        try {  
            //使用資料庫連線手動進行事務提交  
            con.commit();  
        }  
        catch (SQLException ex) {  
            throw new TransactionSystemException("Could not commit JDBC transaction", ex);  
        }  
    }  
    //事務回滾  
    protected void doRollback(DefaultTransactionStatus status) {  
        //獲取事務物件  
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();  
        //通過事務物件獲取資料庫連線  
        Connection con = txObject.getConnectionHolder().getConnection();  
        if (status.isDebug()) {  
            logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");  
        }  
        try {  
            //通過呼叫資料庫連線的回滾方法完成事務回滾操作  
            con.rollback();  
        }  
        catch (SQLException ex) {  
            throw new TransactionSystemException("Could not roll back JDBC transaction", ex);  
        }  
    }  
    //設定回滾  
    protected void doSetRollbackOnly(DefaultTransactionStatus status) {  
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();  
        if (status.isDebug()) {  
            logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() +  
                    "] rollback-only");  
        }  
        txObject.setRollbackOnly();  
    }  
    //操作完成之後清除操作  
    protected void doCleanupAfterCompletion(Object transaction) {  
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;  
        //移除當前執行緒繫結的ConnectionHolder  
        if (txObject.isNewConnectionHolder()) {  
    TransactionSynchronizationManager.unbindResource(this.dataSource);  
        }  
        Connection con = txObject.getConnectionHolder().getConnection();  
        try {  
        //如果事務物件儲存了自動事務提交屬性,則設定資料庫連線的自動事務提交屬性  
            if (txObject.isMustRestoreAutoCommit()) {  
                con.setAutoCommit(true);  
            }  
            //事務結束後重置資料庫連線  
            DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());  
        }  
        catch (Throwable ex) {  
            logger.debug("Could not reset JDBC Connection after transaction", ex);  
        }  
        //如果事務物件中有新的ConnectionHolder   
        if (txObject.isNewConnectionHolder()) {  
            if (logger.isDebugEnabled()) {  
                logger.debug("Releasing JDBC Connection [" + con + "] after transaction");  
            }  
            //釋放資料庫連線  
            DataSourceUtils.releaseConnection(con, this.dataSource);  
        }  
        //清除事務物件的ConnectionHolder  
        txObject.getConnectionHolder().clear();  
    }  
//資料來源事務物件,內部類  
    private static class DataSourceTransactionObject extends JdbcTransactionObjectSupport {  
        //是否有新的ConnectionHolder  
        private boolean newConnectionHolder;  
        //是否儲存自動提交  
        private boolean mustRestoreAutoCommit;  
        //設定ConnectionHolder  
        public void setConnectionHolder(ConnectionHolder connectionHolder, boolean newConnectionHolder) {  
            //為父類JdbcTransactionObjectSupport設定ConnectionHolder  
            super.setConnectionHolder(connectionHolder);  
            this.newConnectionHolder = newConnectionHolder;  
        }  
        public boolean isNewConnectionHolder() {  
            return this.newConnectionHolder;  
        }  
        //呼叫父類JdbcTransactionObjectSupport的相關方法,查詢收費存在事務  
        public boolean hasTransaction() {  
            return (getConnectionHolder() != null && getConnectionHolder().isTransactionActive());  
        }  
        //設定是否儲存自動提交  
        public void setMustRestoreAutoCommit(boolean mustRestoreAutoCommit) {  
            this.mustRestoreAutoCommit = mustRestoreAutoCommit;  
        }  
        public boolean isMustRestoreAutoCommit() {  
            return this.mustRestoreAutoCommit;  
        }  
        //設定資料庫連線在操作失敗是,是否只回滾處理  
        public void setRollbackOnly() {  
            getConnectionHolder().setRollbackOnly();  
        }  
        public boolean isRollbackOnly() {  
            return getConnectionHolder().isRollbackOnly();  
        }  
    }  
}  


相關推薦

Spring技術內幕——DataSourceTransactionManager

Spring的事務處理中,通用的事務處理流程框架是由抽象事務管理器AbstractPlatformTransactionManager來提供的,而具體的底層事務處理實現,由PlatformTransactionManager的具體實現類來實現,如 DataSourceTra

Spring技術內幕Spring AOP的實現原理(三)

dede ide configure ida mini == src min dem 生成SingleTon代理對象在getSingleTonInstance方法中完畢,這種方法時ProxyFactoryBean生成AopProxy對象的入口。代理對象會

Spring技術內幕》筆記-Spring的設計理念和總體架構

ace app flex nfa 使用 架構 非關系型數據庫 ack pri 1。Spring的主要子項目: ????-1。Spring Framework(Cor

spring技術內幕筆記1

springspring的設計目標(為什麽要用spring) 如果我們要簡要地描述Spring的設計目標,可以這麽說,Spring為開發者提供的是一個一站式的輕量級應用開發框架(平臺)。作為平臺,Spring抽象了我們在許多應用開發中遇到的共性問題;同時,作為一個輕量級的應用開發框架,Spring和傳統的J2

Spring技術內幕:設計理念和整體架構概述

spring程序員都很崇拜技術大神,很大一部分是因為他們發現和解決問題的能力,特別是線上出現緊急問題時,總是能夠快速定位和解決。 一方面,他們有深厚的技術基礎,對應用的技術知其所以然,另一方面,在采坑的過程中不斷總結,積累了很多經驗。 相信大家都使用過Spring,有些人了解它的核心:IOC和AOP,但只是了

Spring技術內幕》讀書筆記

處理 計算機系統 web isp 技術內幕 ring 映射 splay str 簡介: 1.spring 與unix、window這些操作在計算機系統中起到的作用是類似的 2.兩大核心模塊:IOC\AOP 3.為應用開發提供了許多現成的系統組件:事務處理、Web MV、JD

Spring技術內幕》---------IoC容器的實現

1.Spring的整體架構 Spring IoC:包含了最基本的IoC容器的BeanFactory的介面與實現。BeanFactory系列容器只實現了最基本的IoC容器的功能;ApplicationContext應用上下文,作為容器的高階形態存在,增加了許多面向框架的特性,包括國際化和應用

Spring技術內幕(一)------理念與架構

1.Spring的各個子專案認識 基於Spring4.x版本的常見模組介紹 1.1 Spring Framework(core) Spring Framework包含了一系列IOC容器的設計,提供了依賴反轉模式的實現;同時還集成了AOP功能.除外還包括Spring的基本模組如MVC,JDBC,事務處理模組的實

Spring技術內幕》---------SpringAop的實現

1.Spring AOP的概述 Aspect是一種新的模組化機制,用來描述分散在物件、類或函式中的橫切關注點 使用AOP後,不僅可以將這些重複的程式碼抽取出來單獨維護,在需要使用時,統一呼叫,還可以為如何使用這些公共程式碼提供豐富靈活的手段。 1.2Advice通知

Spring原始碼解析--《SPRING技術內幕:深入解析Spring架構與設計原理》讀書筆記(一):IOC容器初始化過程

通過閱讀相關章節內容,Spring中IOC容器的載入中,我們需要了解下列幾個概念: Resource:是一個定位、訪問資源的抽象介面,包含了多種資源操作的基礎方法定義,如getInputStream()、exists()、isOpen()、getD

Spring技術內幕》筆記-第二章 IoC容器的實現

簡介 1,在Spring中,SpringIoC提供了一個基本的JavaBean容器,通過IoC模式管理依賴關係,並通過依賴注入和AOP切面增強了為JavaBean這樣子的POJO提供事務管理,生命週期管理等功能。 2,Spring IoC的設計中,主要包含兩個主要的容

Spring技術內幕》學習筆記9——AOP通知以及程式設計式AOP

1.處理AOP配置的通知基本步驟: (1).獲取AOP配置的通知Advice: 從上一篇部落格《》對Spring中採用JDK和CGLIB兩種方式建立AOP動態代理的原始碼分析中,我們瞭解到,在AOP動態代理物件的回撥方法中,都需要使用以下方式獲取AOP配置的通知,並將獲取

spring技術內幕筆記:IoC容器初始化過程(2)- BeanDefinition的載入

Spring版本:4.3.8.RELEASEBeanDefinition載入過程,相當於把定義的BeanDefinition在IoC容器中轉換成一個Spring內部表示的資料結構的過程。IoC容器對Bean的管理和依賴注入功能的實現,就是通過對其持有的BeanDefiniti

Spring技術內幕》學習筆記4——IoC容器解析Bean定義資源並註冊解析後的Bean

原文連結http://blog.csdn.net/chjttony/article/details/6261708 1.通過前兩篇部落格的分析,我們已經瞭解了Spring IoC容器定位和載入Bean定義資原始檔的基本過程,接下來我們要繼續分析Spring IoC容器將載

spring技術內幕讀書筆記--事務處理

事務模組類結構 宣告式事務 宣告式事務處理大致分為以下幾個步驟 1)從配置檔案中讀取事務配置,並將事務元資料轉化為spring內部元資料物件。 涉及類:TransactionAttributeSourceAdvisor(此通知器類會將事務

Spring技術內幕之IOC容器的實現(01)-IOC容器初始化過程

Spring IOC容器的初始化過程 Spring IOC容器的初始化過程主要包括BeanDefinition的Resouce定位/載入/註冊三個基本過程。Spring把這三個過程的實現分別放在不同的模組下,通過這樣的設計方式可以使使用者更加靈活地對這個三個過程進行裁剪和自

Spring技術內幕:深入解析Spring架構與設計原理》筆記之六(Spring事務處理的實現)

1.Spring與事務處理有了Spring事務管理的支援,只需要通過一些簡單的配置,應用就能完成複雜的事務處理工作,從而為使用者使用事務處理提供很大的方便。2.Spring事務處理的設計概覽Spring事務處理模組中的類層次結構在Spring事務處理中,可以通過設計一個Tra

spring技術內幕筆記:IoC容器的初始化過程(3)- BeanDefinition的註冊

Spring版本:4.3.8.RELEASE DefaultListableBeanFactory中,通過一個HashMap來持有和載入BeanDefinition,解析得到的BeanDefinition向IoC容器的beanDefinitionMap註冊過程 是在載入B

8-spring原始碼3.2.18解讀+spring技術內幕(IOC容器的依賴注入(反射+遞迴呼叫))

1、導讀 以上對IOC容器的初始化過程做了詳細的分析,這個初始化過程完成的主要工作是在IOC容器中建立BeanDefinition資料對映。再次過程中並沒有對Bean依賴關係進行注入,接下來將分析一下IOC容器是怎麼樣對Bean的依賴關係進行注入的。 假設當前IOC容器已

Spring技術內幕——事務的建立,掛起,迴歸,提交(事務攔截器和抽象事務管理器)

在涉及單個數據庫區域性事務的事務處理中,事務的最終實現和資料庫的支援是緊密相關的。對區域性資料庫事務來說,一個事務處理的操作單元往往對應著一系列的資料庫操作。 Spring事務處理主要分以下三個主要的過程: (1)讀取和處理在Spring IoC容器中配置的事務處理屬性,並