Spring事务架构详解一:PlatformTransactionManager

 一、PlatformTransactionManager

       1、架构设计理念让事务的关注点与数据访问关注点分离

       2、PlatformTransactionManager是该架构的核心接口,为应用程序提供事务界定的统一方式

        3、PlatformTransactionManager负责界定事务边界,TransactionDefinition负责定义事务属性(隔离级别、传播行为),PlatformTransactionManager将参照TransactionDefinition的属性定义来开启相关事务。事务开启之后到事务结束期间的事务状态由TransactionStatus负责,我们也可以通过TransactionStatus对事务进行有限的控制。·

类图

1、Spring的事务抽象框架以PlatformTransactionManager作为顶层抽象接口,具体的实现交给不同的实现类,使用对象可以根据当前场景,选择使用或者替换哪一个具体的实现类。从这个层次看,整个框架的设计是以Strategy模式为基础的。不过,从各个实现类的继承层次上来看,Spring 事务框架的实现则更多地依赖于模板方法模式。

2、org.springframework.transaction.support.AbstractPlatformTransactionManager作为DataSourceTransactionManager的父类,以模板方法的形式封装了固定的事务处理逻辑,而只将与事务资源相关的操作以protected或者abstract方法的形式留给DataSourceTransactionManager 来实现。作为模板方法父类,AbstractPlatformTransactionManager替各子类实现了以下固定的?N 务内部处理逻辑:

□判定是否存在当前事务,然后根据判断结果执行不同的处理逻辑;

□结合是否存在当前事务的情况,根据TransactionDefinition中指定的传播行为的不同语义执行后继逻辑;

□根据情况挂起或者恢复事务;

□提交事务之前检查readonly字段是否被设置,如果是的话,以事务的回滚代替事务的提交;

□在事务回滚的情况下,清理并恢复事务状态:

□如果事务的Synchonization处于active状态,在事务处理的规定时点触发注册的Synchonization 回调接口。

这些固定的事务内部处理逻辑大都体现在以下几个主要的模板方法中:

□ public final Transactionstatus getTrcinsaction(TransactionDefinitiondefinition) throws TransactionException

□ public final void rollback(Transactionstatus status) throws TransactionException

□ public final void commit(Transactionstatus status) throws TransactionException

□ protected final SuspendedResourcesHolder suspend(0bject transaction) throws TransactionException

□ protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder) throws TransactionException

下面详细介绍几个模板方法:

2.1、getTransaction(TransactionDefinition)开始。getTransaction (TransactionDefinition)的主要目的是开启一个事务,但需要在此之前判断一下之前是否存在一个事务。如果存在,则根据TransactionDefinition中的传播行为决定是挂起当前事务还是抛出异常。同样的,不存在事务的情况下,也需要根据传播行为的具体语义来决定如何处理。

1)获取transaction object,以判断是否存在当前事务。

以上这行代码有如下两点需要申明。

□ 获取的transaction object类型会因具体实现类的不同而各异,DataSourceTransactionManager 会返回DataSourceTransactionManager. DataSourceTransacCionObject 类型实例,HibernateTransactionManager会返回HibernateTransactionManager.HibernateTransactionObject类型的实例,等等。AbstractPlatformTransactionManager不需要知道具体实现类返回的transaction object具体类型是什么,因为最终对transaction object的依赖都将通过方法参数进行传递,只要具体的实现类在取得transaction object参数后知道如何转型就行,所以,这一步返回的transact ion为Object类型。

□ doGetTransaction()是getTransaction(TransactionDefinition)模板方法公开给子类来实现的abstract 类型方法。DataSourceTransactionManager 在实现doGetTransaction ()方法逻辑的时候,会从TransactionSynchronizationManager获取绑定的资源,然后添加到DataSourceTransactionObject之后返回。

2)检验TransactionDefinition参数合法性。如以下代码所示:

if (definition == null)(

        definition = new DefaultTransactionDefinition

)

如果definition参数为空,则创建一个DefaultTransactionDefinition实例以提供默认的事务定义数据。

3)根据先前获得的transaction object判断是否存在当前事务,根据判定结果采取不同的处理方式。

默认情况下,isExistingTransaction(transaction)返回false,该方法需要具体子类根据情况进行覆写。对于DataSourceTransactionManager来说,它会根据传入的transaction所记载的信息进行判断,如下所示:

(a)如果isExistingTransaction(transaction)方法返回true,即存在当前事务的情况下,由handleExistingTransaction ()方法统处理存在当前事务,应该如何创建事务对应的Transactionstatus 实例并返回。

如果definition定义的传播行为是PROPAGATI0N_NEVER,抛出异常并退出.如下:

如果definition定义的传播行为是PROPAGATION_NOT_SUPPORTED,则挂起当前事务,然后返回. 如下:

newTransactionStatus()方法返回一个DefaultTransactionStatus实例,因为我们挂起了当前事务。而PROPAGATION_NOT_SUPPORTED不需要事务,所以,返回的DefaultTransactionStatus 不包含transaction object的信息(构造方法第二个参数)。

如果definition定义的传播行为是PROPAGATION-REQUIRES_NEW,则同样挂起当前事务,并开始—个新的事务并返回.如下:

AbstractPlatformTransactionManager首先将当前事务挂起,然后调用doBegin()方法开始新的事务。如果开始事务过程中出现异常,那么恢复之前挂起的事务。doBegin(transaction, definition)方法为abstract方法,需要具体子类来实现。在DataSourceTransactionManager的doBegin()方法会首先检查传入的transaction以提取必要信息判断之前是否存在绑定的connection信息。如果没有,则从DataSource中获取新的connection,然后将其AutoCoiranit状态改为false,并绑定到TransactionSynchronizationManager。当然,这期间也会涉及事务定义的应用以及条件检查等逻辑。在所有一切搞定之后,newTransactionStatus会创建一个包含definition、transaction object以及挂起的事务信息和其他状态信息的DefaultTransactionStatus 实例并返回。

如果definition定义的传播行为是PROPAGATIONJNESTED,根据情况创建嵌套事务,如通过Savepoint或者JTA的TransactionManager.如下:


在这种情况下,会首先通过isNestedTransactionAllowed ()方法检查AbstractPlatform-TransactionManager的nestedTransactionAllowed属性状态。如果允许嵌套事务,那么还得分两种情况处理。对于DataSourceTransactionManager来说,因为它支持使用Savepoint创建嵌套事务,所以,会使用Transactionstatus创建相应的Savepoint并返回。而JtaTransactionManager则要依赖于具体JTA产品的TransactionManager提供嵌套事务支持。

useSavepointForNestedTransaction()方法默认返回true,即默认使用Savepoint创建嵌套事务。如果具体子类不支持使用Savepoint创建嵌套事务,则需要覆写该方法,如JtaTransactionManager。

(b)如果isExistingTransaction (transaction)方法返回false.即不存在当前事务的情况下。

当definition中定义的传播行为是PROPAGATION_MANDATORY的时候,抛出异常.因为不存在当 前事务,所以根据PROPAGATION-MANDATORY的语义,理当如此.

当definition中定义的传播行为是PROPAGATION_REQUIRED» PROPAGATION_REQUIRES_NEW或者PROPAGATION_NESTED的时候,开启新的事务.如下:


之所以在doBegin之前先调用传入null的suspend()方法,是因为考虑到如果有注册Synchronization. 需要暂时将这些与将要开启的新事务无关的Synchronization先放一边。

剩下的其他情况,则返回不包含任何transaction object的Transactionstatus,这种情况下虽然是空的事务,但有可能需要处理在事务过程中相关的Synchronization。

从getTransaction (TransactionDefinition)的逻辑可以看出AbstractPlat formTran- sactionManager更多关注的是事务处理过程中的总体逻辑,而跟具体事务资源相关的处理则交给了具体的子类来实现。

2.2  事务处理的完成有两种情况,即回滚事务或者提交事务,AbstractPlatformTransactionManager提供的rollback (Transactionstatus)和commit (Transactionstatus)两个模板方法,分别对应这两种情况下的处理。因为事务提交过程中可能需要处理回滚逻辑,我们不妨以commit (Transactionstatus)的实现流程看一下AbstractPlatformTransactionManager 是如何处理事务完成的。

(1)因为在事务处理过程中,我们可以通过Transactionstatus的setRollbackOnly ()方法标记 事务回滚,所以,commit (Transactionstatus)在具体提交事务之前会检查rollBackOnly状态。如果该状态被设置,那么转而执行事务的回滚操作。


rollback (Transactionstatus)的逻辑主要包含如下3点。

□回滚事务。这里的回滚事务又可分为如下3种情况。

■如果是嵌套事务,则通过Transactionstatus释放Savepoint。

■如果Transactionstatus表示当前事务是一个新的事务,则调用子类的doRollback (Transactionstatus)方法真正的回滚事务。doRollback(Transactionstatus)是抽象方法,具体子类必须实现它。DataSourceTransactionManager在实现该方法的时候,无疑是调用connection.rollback()。HibernateTransactionManager会通过它Session上的Transaction 的rollback()方法回滚事务。其他子类对doRollback (TransactionStatus) 的实现逻辑依此类推。

■如果当前存在事务,并且rollbackOnly状态被设置,则调用由子类实现的doSet- RollbackOnly (Transactionstatus)方法,各子类实现通常会将当前的transaction object 的状态设置为rollBackOnly。

□触发Synchronization 事件。

回滚时触发的事件比提交时触发的事件要少,只有triggerBeforeCompletion (status)和triggerAfterCompletion。

□清理事务资源。如下所述。

■设置Transactionstatus 中的completed 为完成状态。

■清理与当前事务相关的Synchronization。

■调用doCleanupAfterCompletion() 放事务资源,并解除到Transaction SynchronizationManager的资源绑定。对于DataSourceTransactionManager来说,是关闭数据库连接,然后解除对Datasource对应资源的绑定。

■如果之前有挂起的事务,恢复挂起的事务。

(2)如果rollBackOnly状态没被设置则执行正常的事务提交操作。

commit (TransactionStatus)方法的其他逻辑与rollback (Transactionstatus)方法基本相似,只是几个具体操作有所差别,如下所述。

□回滚事务现在变成是提交事务。提交事务的时候,也会涉及如下几种情况。

■决定是否提前检测全局的rollBackOnly标志。如果最外层事务己经被标记为rollBackOnly 并且failEarlyOnGlobalRollbackOnly为 true,则抛出异常。

■如果提交事务之前发现Transactionstatus持有Savepoint,则释放它。这实际上是在处理恢套事务的提交。

■如果Transactionstatus表示要提交的事务是一个新的事务,则调用子类的doCoimit (TransactionStatus)方法实现提交事务。doConunit (Transactionstatus)也是Abstract Plat formTransact ionManager 公开给子类实现的抽象方法,子类必须实现该方法。对于DataSourceTransactionManager来说,因为事务的提交由Connection决定,所以会直接调用connection. commit ()提交事务。其他的子类也会使用自身的局部事务API在该方法中实现事务的提交。

□需要触发Synchronization相关事件。不过,触发的事件比rolIback (TransactionStatus)中的要多,包括triggerBeforeCoiranit() triggerBeforeCompletion() > triggerAfterCommit ()和triggerAfterCompletion()

□ 如果AbstractplatformTransactionManager 的rollbackOnCommitFailure 状态被设置为true,则表示如果在事务提交过程中出现异常,需要回滚事务。所以,当commit (Transactionstatus) 方法捕获相应异常,并且检测到该字段被设置的时候,需要回滚事务。rollbackOnConunitFailure的默认值是false,表示即使提交过程中出现异常,也不回滚事务。

□既然commit (Transactionstatus)与rolIback(TransactionStatus)~~样,都是意味着事务的完成,那么也需要在最后进行事务资源清理的工作,具体内容可以参照rollback (Transactionstatus)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容