spring-tx,spring-jdbc模塊筆記,只涉及事務(wù)部分
核心類
@EnableTransactionManagement:引入TransactionManagementConfigurationSelector,根據(jù)參數(shù)判斷proxy/aspectj載入不同的解析對(duì)象,proxy模式下載入AutoProxyRegistrar和ProxyTransactionManagementConfiguration.
AutoProxyRegistrar:將InfrastructureAdvisorAutoProxyCreator加入到容器中.它將框架基礎(chǔ)設(shè)施Advisor(role=BeanDefinition.ROLE_INFRASTRUCTURE)生成對(duì)應(yīng)的aop代理
ProxyTransactionManagementConfiguration:載入了基于注解的aop基礎(chǔ)設(shè)施Bean.主要是將解析注解的Advisor對(duì)象加入到容器中
TransactionAttributeSource:事務(wù)源信息的獲取策略接口,載入的是AnnotationTransactionAttributeSource類,用于處理@Transaction注解
TransactionInterceptor-TransactionAspectSupport-invokeWithinTransaction執(zhí)行流程
BeanFactoryTransactionAttributeSourceAdvisor:通過StaticMethodMatcherPointcut將方法級(jí)過濾轉(zhuǎn)移到TransactionAttributeSource進(jìn)行判斷,advice部分轉(zhuǎn)到TransactionInterceptor進(jìn)行實(shí)現(xiàn).自身作為advisor加入到容器
事務(wù)管理器-事務(wù)的流程抽象
PlatformTransactionManager:事務(wù)管理器接口定義,使用較多的是DataSourceTransactionManager.它是以DataSource中的connection抽象的事務(wù)對(duì)象
TransactionStatus:存儲(chǔ)事務(wù)對(duì)象,掛起的上一個(gè)事務(wù)對(duì)象以及額外事務(wù)屬性的接口.它是主要的中間數(shù)據(jù),用于存儲(chǔ)原始連接信息以便后續(xù)的恢復(fù)連接信息
TransactionDefinition:事務(wù)屬性接口.傳播屬性,隔離級(jí)別,只讀等.它的實(shí)現(xiàn)主要是DefaultTransactionDefinition
TransactionTemplate:繼承DefaultTransactionDefinition,自身即含有事務(wù)狀態(tài),同時(shí)引入了PlatformTransactionManager進(jìn)行事務(wù)操作,還實(shí)現(xiàn)了
TransactionOperations接口,提供了手工事務(wù)操作入口.
核心流程
首先通過TransactionManager的getTransaction(td)方法獲得TransactionStatus對(duì)象,后面執(zhí)行對(duì)應(yīng)的回調(diào)方法,如果出異常那么回滾,如果正常執(zhí)行完成,那么提交操作,這兩個(gè)操作都需要之前返回的TransactionStatus對(duì)象作為入?yún)?
以DataSourceTransactionManager為例,描述完整的事務(wù)管理過程
getTransaction()方法,先通過doGetTransaction抽象方法獲取事務(wù)對(duì)象,事務(wù)對(duì)象是子類自己定義的,這里用的是DataSourceTransactionObject類,在doGetTransaction方法只是新建了DataSourceTransactionObject對(duì)象,嘗試通過ThreadLocal獲取之前的ConnectionHolder設(shè)置到當(dāng)前事務(wù)對(duì)象中.
然后判斷當(dāng)前線程是否存在被激活的事務(wù)(這里根據(jù)是否存在當(dāng)前事務(wù)對(duì)傳播屬性進(jìn)行了實(shí)現(xiàn))
如果有事務(wù)
那么檢查事務(wù)傳播行為,做出對(duì)應(yīng)的操作,直接返回結(jié)果
事務(wù)傳播行為對(duì)應(yīng)的操作(獲取連接=實(shí)際根據(jù)屬性進(jìn)行連接配置)
PROPAGATION_NEVER-拋異常
PROPAGATION_NOT_SUPPORTED-掛起當(dāng)前事務(wù),生成一個(gè)空的DefaultTransactionStatus返回(在非事務(wù)中執(zhí)行)
PROPAGATION_REQUIRES_NEW-掛起當(dāng)前事務(wù),將原事務(wù)對(duì)象與被掛起的資源放入DefaultTransactionStatus對(duì)象,并獲取連接(新建事務(wù))
PROPAGATION_NESTED-不掛起當(dāng)前事務(wù),將原事務(wù)對(duì)象放入DefaultTransactionStatus對(duì)象,并獲取連接(支持嵌套才可以,如果是DataSourceTM那么實(shí)際上還是同一連接)
其他情況-不掛起當(dāng)前事務(wù),將原事務(wù)對(duì)象放入DefaultTransactionStatus對(duì)象,直接返回,不獲取連接(支持當(dāng)前事務(wù)運(yùn)行PROPAGATION_REQUIRED或PROPAGATION_SUPPORTS)
如果沒有事務(wù)
根據(jù)對(duì)應(yīng)的傳播屬性做出對(duì)應(yīng)的操作并返回
PROPAGATION_MANDATORY-拋異常
PROPAGATION_REQUIRED&PROPAGATION_REQUIRES_NEW&PROPAGATION_NESTED-那么執(zhí)行以下操作
新建TransactionStatus對(duì)象(DefaultTransactionStatus),執(zhí)行doBegin抽象方法,這里doBegin方法先判斷事務(wù)對(duì)象是否有連接,如果沒有連接,那么調(diào)用DataSource.getConnection獲取一個(gè)新連接并包裝成ConnectionHolder對(duì)象放入事務(wù)對(duì)象內(nèi).然后對(duì)連接屬性進(jìn)行設(shè)置,有隔離級(jí)別,手動(dòng)提交.還要讀取Definition信息設(shè)置ConnectionHolder對(duì)象的屬性.同時(shí)將之前的連接信息存儲(chǔ)到事務(wù)對(duì)象中,用于后續(xù)提交或者回滾后恢復(fù)連接屬性操作.后面繼續(xù)判斷如果是新連接,那么線程綁定事務(wù)對(duì)象,同時(shí)設(shè)置事務(wù)激活狀態(tài),綁定事務(wù)隔離級(jí)別,只讀屬性,名稱等.返回TransactionStatus對(duì)象,讓使用者在可以拿到事務(wù)的屬性信息.結(jié)束創(chuàng)建事務(wù)流程.
其他情況-生成一個(gè)空的DefaultTransactionStatus返回(在非事務(wù)中執(zhí)行,如PROPAGATION_SUPPORTS,PROPAGATION_NOT_SUPPORTED)
中間在事務(wù)中執(zhí)行對(duì)應(yīng)的sql.
詳細(xì)說下這里連接對(duì)象的獲取過程.對(duì)于mybatis-spring來說,使用的是SpringManagedTransaction對(duì)象進(jìn)行管理DataSource來獲取連接的,這里的getConnection會(huì)轉(zhuǎn)到DataSourceUtils的getConnection中,它優(yōu)先判斷從綁定線程中可以獲取對(duì)應(yīng)的ConnectionHolder,并且事務(wù)是被激活的狀態(tài),那么從ConnectionHolder拿出連接直接返回,如果不是的話就獲取真實(shí)連接,再判斷當(dāng)前事務(wù)是否激活,如果是被激活的,那么注冊(cè)ConnectionSynchronization(用于清理資源)和將ConnectionHolder綁定到當(dāng)前線程.最后返回連接對(duì)象
最后如果拋出異常
回滾操作.先觸發(fā)綁定線程中的BeforeCompletion回調(diào),然后調(diào)用connection的rollback,根據(jù)有無異常,觸發(fā)AfterCompletion的回調(diào)并傳入不同參數(shù).最后觸發(fā)AfterCompletion的回調(diào)
如果沒有拋出異常
提交.檢查是否有本地/全局回滾標(biāo)志,如果有的話調(diào)用回滾操作,如果沒有,觸發(fā)BeforeCommit回調(diào),然后BeforeCompletion回調(diào),然后調(diào)用connection的commit.如果有異常觸發(fā)回滾,如果沒有,觸發(fā)AfterCommit回調(diào),最后觸發(fā)AfterCompletion回調(diào),然后進(jìn)行清理過程,清理掉所有線程綁定的對(duì)象,恢復(fù)連接屬性(自動(dòng)提交,隔離級(jí)別,只讀屬性),恢復(fù)之前掛起的事務(wù).當(dāng)前事務(wù)結(jié)束
事務(wù)特點(diǎn)
1.原子性:一個(gè)事務(wù)中所有對(duì)數(shù)據(jù)庫的操作是一個(gè)不可分割的操作序列颤殴,要么全做要么全不做
2.一致性:數(shù)據(jù)不會(huì)因?yàn)槭聞?wù)的執(zhí)行而遭到破壞
3.隔離性:一個(gè)事物的執(zhí)行李皇,不受其他事務(wù)的干擾册着,即并發(fā)執(zhí)行的事物之間互不干擾
4.持久性:一個(gè)事物一旦提交磕谅,它對(duì)數(shù)據(jù)庫的改變就是永久的菩鲜。
七個(gè)事務(wù)傳播屬性—傳播屬性的實(shí)現(xiàn)是spring實(shí)現(xiàn)的,有些傳播屬性(比如PROPAGATION_NESTED)主要是JTA考慮的
PROPAGATION_REQUIRED -- 支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù)葵礼,就新建一個(gè)事務(wù)萨醒。這是最常見的選擇。
PROPAGATION_SUPPORTS -- 支持當(dāng)前事務(wù)写妥,如果當(dāng)前沒有事務(wù)拳球,就以非事務(wù)方式執(zhí)行。
PROPAGATION_MANDATORY -- 支持當(dāng)前事務(wù)珍特,如果當(dāng)前沒有事務(wù)祝峻,就拋出異常。
PROPAGATION_REQUIRES_NEW -- 新建事務(wù)扎筒,如果當(dāng)前存在事務(wù)莱找,把當(dāng)前事務(wù)掛起。
PROPAGATION_NOT_SUPPORTED -- 以非事務(wù)方式執(zhí)行操作嗜桌,如果當(dāng)前存在事務(wù)奥溺,就把當(dāng)前事務(wù)掛起。
PROPAGATION_NEVER -- 以非事務(wù)方式執(zhí)行骨宠,如果當(dāng)前存在事務(wù)浮定,則拋出異常。
PROPAGATION_NESTED--如果當(dāng)前存在事務(wù)层亿,則在嵌套事務(wù)內(nèi)執(zhí)行壶唤。如果當(dāng)前沒有事務(wù),則進(jìn)行與PROPAGATION_REQUIRED類似的操作棕所。
五種隔離級(jí)別—隔離級(jí)別的實(shí)現(xiàn)是依靠數(shù)據(jù)庫自身實(shí)現(xiàn)的
隔離級(jí)別是指若干個(gè)并發(fā)的事務(wù)之間的隔離程度闸盔。
ISOLATION_DEFAULT--這是一個(gè)PlatfromTransactionManager默認(rèn)的隔離級(jí)別,使用數(shù)據(jù)庫默認(rèn)的事務(wù)隔離級(jí)別.另外四個(gè)與JDBC的隔離級(jí)別相對(duì)應(yīng)琳省;
ISOLATION_READ_UNCOMMITTED--這是事務(wù)最低的隔離級(jí)別迎吵,它充許別外一個(gè)事務(wù)可以看到這個(gè)事務(wù)未提交的數(shù)據(jù)。這種隔離級(jí)別會(huì)產(chǎn)生臟讀针贬,不可重復(fù)讀和幻像讀击费。
ISOLATION_READ_COMMITTED--保證一個(gè)事務(wù)修改的數(shù)據(jù)提交后才能被另外一個(gè)事務(wù)讀取。另外一個(gè)事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)桦他。這種事務(wù)隔離級(jí)別可以避免臟讀出現(xiàn)蔫巩,但是可能會(huì)出現(xiàn)不可重復(fù)讀和幻像讀。
ISOLATION_REPEATABLE_READ--這種事務(wù)隔離級(jí)別可以防止臟讀,不可重復(fù)讀圆仔。但是可能出現(xiàn)幻像讀垃瞧。它保證了一個(gè)事務(wù)中的所有讀取操作時(shí)一致的結(jié)果,不受事務(wù)中其他事務(wù)提交的影響.但是會(huì)產(chǎn)生幻讀,比如說范圍查詢時(shí),每次查詢結(jié)果是一致的,但是其他事務(wù)新插入了符合條件的行,導(dǎo)致執(zhí)行的范圍更新比查詢結(jié)果多,就像產(chǎn)生的幻覺.部分?jǐn)?shù)據(jù)庫在RR級(jí)別已經(jīng)可以解決幻讀的問題了
ISOLATION_SERIALIZABLE--這是花費(fèi)最高代價(jià)但是最可靠的事務(wù)隔離級(jí)別。事務(wù)被處理為順序執(zhí)行坪郭。除了防止臟讀个从,不可重復(fù)讀外,還避免了幻像讀歪沃。