Spring聲明式事務(wù)管理源碼解讀之事務(wù)開(kāi)始
相關(guān)文章:Spring聲明式事務(wù)管理源碼解讀之事務(wù)提交
在spring的聲明式事務(wù)管理中,它是如何判定一個(gè)及標(biāo)記一個(gè)方法是否應(yīng)該是處在事務(wù)體之中呢。
首先要理解的是spring是如何來(lái)標(biāo)記一個(gè)方法是否應(yīng)該處在事務(wù)體之中的。有這樣一個(gè)接口TransactionDefinition,其中定義了很多常量,它還有一個(gè)子接口TransactionAttribute,其中只有一個(gè)方法rollback。
TransactionDefinition中有很多常量定義,它們分別屬于兩種類(lèi)型,傳播途徑和隔離級(jí)別
代碼:
/** *Supportacurrenttransaction,createanewoneifnoneexists. *AnalogoustoEJBtransactionattributeofthesamename. * |
當(dāng)然其中也定義了隔離級(jí)別
/**
代碼
*Aconstantindicatingthatdirtyreadsareprevented;non-repeatablereads |
同時(shí)還有兩個(gè)對(duì)應(yīng)的方法來(lái)得到這樣的傳播途徑和隔離級(jí)別
代碼
/** |
這個(gè)接口有一個(gè)默認(rèn)的實(shí)現(xiàn)DefaultTransactionDefinition。然后它還有子類(lèi),比如說(shuō)
DefaultTransactionAttribute。Spring在判斷一個(gè)方法是否需要事務(wù)體的時(shí)候其實(shí)是創(chuàng)建一個(gè)TransactionAttribute實(shí)現(xiàn)的實(shí)例.
有了上面的簡(jiǎn)單介紹就可以進(jìn)入真正判斷是否需要事務(wù)的地方了。這個(gè)方法在TransactionAspectSupport類(lèi)里,
代碼
/** *Createatransactionifnecessary. *@parammethodmethodabouttoexecute *@paramtargetClassclassthemethodison *@returnaTransactionInfoobject,whetherornotatransactionwascreated. *ThehasTransaction()methodonTransactionInfocanbeusedtotellifthere *wasatransactioncreated. */ protectedTransactionInfocreateTransactionIfNecessary(Methodmethod,ClasstargetClass){ //Ifthetransactionattributeisnull,themethodisnon-transactional. finalTransactionAttributesourceAttr= this.transactionAttributeSource.getTransactionAttribute(method,targetClass);//就是在這里判斷了這個(gè)方法的事務(wù)屬性 TransactionAttributetxAttr=sourceAttr; //Ifnonamespecified,applymethodidentificationastransactionname. if(txAttr!=null&&txAttr.getName()==null){ finalStringname=methodIdentification(method); txAttr=newDelegatingTransactionAttribute(sourceAttr){ publicStringgetName(){ returnname; } }; } TransactionInfotxInfo=newTransactionInfo(txAttr,method); //TransactionInfo是TransactionAspectSupport的一個(gè)內(nèi)部類(lèi),它的主要功能是記錄方法和對(duì)應(yīng)的事務(wù)屬性 if(txAttr!=null){ //Weneedatransactionforthismethod if(logger.isDebugEnabled()){ logger.debug("Gettingtransactionfor"+txInfo.joinpointIdentification()); } //Thetransactionmanagerwillflaganerrorifanincompatibletxalreadyexists txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));//這個(gè)方法要仔細(xì)的看 } else{ //TheTransactionInfo.hasTransaction()methodwillreturn //false.Wecreateditonlytopreservetheintegrityof //theThreadLocalstackmaintainedinthisclass. if(logger.isDebugEnabled()) logger.debug("Don'tneedtocreatetransactionfor["+methodIdentification(method)+ "]:thismethodisn'ttransactional"); } //WealwaysbindtheTransactionInfotothethread,evenifwedidn'tcreate //anewtransactionhere.ThisguaranteesthattheTransactionInfostack //willbemanagedcorrectlyevenifnotransactionwascreatedbythisaspect. txInfo.bindToThread(); returntxInfo; }
TransactionInfo是TransactionAspectSupport的一個(gè)內(nèi)部類(lèi),它的主要功能是記錄方法和對(duì)應(yīng)的事務(wù)屬性,在上面這個(gè)方法的***,這個(gè)TransactionInfo對(duì)象被保存到當(dāng)前線程中。
#p#
而這個(gè)方法會(huì)在事務(wù)攔截器TransactionInterceptor中被調(diào)用,TransactionInterceptor實(shí)際上是TransactionAspectSupport的子類(lèi),看看其中的invoke方法:
代碼
null
. //TheTransactionAttributeSourceshouldbepassedthetargetclass
//aswellasthemethod,whichmaybefromaninterface
ClasstargetClass=(invocation.getThis()!=null)?invocation.getThis().getClass():null;
//Createtransactionifnecessary.
TransactionInfotxInfo=createTransactionIfNecessary(invocation.getMethod(),targetClass);
ObjectretVal=null;
try{
//Thisisanaroundadvice.
//Invokethenextinterceptorinthechain.
//Thiswillnormallyresultinatargetobjectbeinginvoked.
retVal=invocation.proceed();
}
catch(Throwableex){
//targetinvocationexception
doCloseTransactionAfterThrowing(txInfo,ex);
throwex;
}
finally{
doFinally(txInfo);
}
doCommitTransactionAfterReturning(txInfo);//在這里執(zhí)行方法結(jié)束之后需要的操作
returnretVal;
這個(gè)方法就如同一般的interceptor需要實(shí)現(xiàn)的方法一樣。只不過(guò)在這個(gè)方法里判斷被反射的方法是否需要事務(wù)。
接著我們重點(diǎn)再回頭看一下createTransactionIfNecessary方法里的這一句:
txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr)); |
接著我們就應(yīng)該去看看這個(gè)getTransaction方法了,假設(shè)我們是使用hibernate3,其他類(lèi)似??磄etTransaction之前我們來(lái)看一下這兩類(lèi)和一個(gè)接口
接口PlatformTransactionManager
抽象類(lèi)public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager
類(lèi)public class HibernateTransactionManager extends AbstractPlatformTransactionManager,很明顯,這里有一個(gè)方法模板模式。
那我們看一下AbstractPlatformTransactionManager中的getTransaction方法:
代碼
Objecttransaction=doGetTransaction();//抽象方法,也需要子類(lèi)實(shí)現(xiàn),這個(gè)方法同樣很重要
//Cachedebugflagtoavoidrepeatedchecks.
booleandebugEnabled=logger.isDebugEnabled();
if(debugEnabled){
logger.debug("Usingtransactionobject["+transaction+"]");
}
if(definition==null){
//Usedefaultsifnotransactiondefinitiongiven.
definition=newDefaultTransactionDefinition();
}
if(isExistingTransaction(transaction)){
//Existingtransactionfound->checkpropagationbehaviortofindouthowtobehave.
returnhandleExistingTransaction(definition,transaction,debugEnabled);
}
//Checkdefinitionsettingsfornewtransaction.
if(definition.getTimeout()
}
//Noexistingtransactionfound->checkpropagationbehaviortofindouthowtobehave.
if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_MANDATORY){
thrownewIllegalTransactionStateException(
"Transactionpropagation'mandatory'butnoexistingtransactionfound");
}
elseif(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRED||
definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRES_NEW||
definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NESTED){
if(debugEnabled){
logger.debug("Creatingnewtransactionwithname["+definition.getName()+"]");
}
doBegin(transaction,definition);
booleannewSynchronization=(this.transactionSynchronization!=SYNCHRONIZATION_NEVER);
returnnewTransactionStatus(definition,transaction,true,newSynchronization,debugEnabled,null);
}
else{
//Create"empty"transaction:noactualtransaction,butpotentiallysynchronization.
booleannewSynchronization=(this.transactionSynchronization==SYNCHRONIZATION_ALWAYS);
returnnewTransactionStatus(definition,null,false,newSynchronization,debugEnabled,null);
}
}
上面的代碼很多地方都有解釋?zhuān)院芎美斫?,這段代碼的關(guān)鍵部分在doBegin(transaction,definition)這里(這是一個(gè)抽象方法,子類(lèi)必須實(shí)現(xiàn)這個(gè)方法,
具體依賴于抽象,這個(gè)是對(duì)方法模板模式的一個(gè)概括。),前面講到我們假設(shè)是使用hibernate,那么就看看HibernateTransactionManager這個(gè)類(lèi)吧,doBegin里的參數(shù)1,transaction其實(shí)是HibernateTransactionObject的一個(gè)實(shí)例,這個(gè)實(shí)例里主要存放的就是sessionholder,sessionholder里存放的就是開(kāi)始事務(wù)的session和transaction對(duì)象,如果之前沒(méi)有sessionholder存放到線程中,那么這個(gè)HibernateTransactionObject的實(shí)例的屬性其實(shí)是空的,這一點(diǎn)可以在doBegin方法的實(shí)現(xiàn)中看出來(lái)
代碼
protectedvoiddoBegin(Objecttransaction,TransactionDefinitiondefinition){
if(getDataSource()!=null&&TransactionSynchronizationManager.hasResource(getDataSource())){
thrownewIllegalTransactionStateException(
"Pre-boundJDBCConnectionfound-HibernateTransactionManagerdoesnotsupport"+
"runningwithinDataSourceTransactionManageriftoldtomanagetheDataSourceitself."+
"ItisrecommendedtouseasingleHibernateTransactionManagerforalltransactions"+
"onasingleDataSource,nomatterwhetherHibernateorJDBCaccess.");
}
Sessionsession=null;
try{
HibernateTransactionObjecttxObject=(HibernateTransactionObject)transaction;
if(txObject.getSessionHolder()==null){
InterceptorentityInterceptor=getEntityInterceptor();
SessionnewSession=(entityInterceptor!=null?
getSessionFactory().openSession(entityInterceptor):getSessionFactory().openSession());
if(logger.isDebugEnabled()){
logger.debug("OpenednewSession["+newSession+"]forHibernatetransaction");
}
txObject.setSessionHolder(newSessionHolder(newSession),true);}//
我們看到,如果傳進(jìn)來(lái)的transaction中并沒(méi)有存放sessionholder,那么就新建一個(gè)session,放到新的sessionholder中,再放到HibernateTransactionObject的實(shí)例中去,順便說(shuō)一下,這個(gè)變量的名字取得真是差,雖然是Juergen Hoeller寫(xiě)的,也要批一下,搞得別人會(huì)以為是Transaction的實(shí)例
代碼
session=txObject.getSessionHolder().getSession();
Connectioncon=session.connection();
IntegerpreviousIsolationLevel=DataSourceUtils.prepareConnectionForTransaction(con,definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
if(definition.isReadOnly()&&txObject.isNewSessionHolder()){
//JustsettoNEVERincaseofanewSessionforthistransaction.
session.setFlushMode(FlushMode.NEVER);
}//如果是只讀事務(wù),并且sessionholder是新建的,那么就設(shè)置hibernate的flushmode為never
if(!definition.isReadOnly()&&!txObject.isNewSessionHolder()){
//WeneedAUTOorCOMMITforanon-read-onlytransaction.
FlushModeflushMode=session.getFlushMode();
if(FlushMode.NEVER.equals(flushMode)){
session.setFlushMode(FlushMode.AUTO);
//如果session的flushmode是nerver,就設(shè)置為auto,因?yàn)槿绻聞?wù)定義成非readonly,那么這個(gè)session一定是可以flush的
txObject.getSessionHolder().setPreviousFlushMode(flushMode);
}
}
//AddtheHibernatetransactiontothesessionholder.
txObject.getSessionHolder().setTransaction(session.beginTransaction());//開(kāi)始一個(gè)事務(wù),并把這個(gè)事務(wù)對(duì)象放到sessionholder中,隨后這個(gè)sessionholder會(huì)通過(guò)threadlocal放到線程中,以供在commit時(shí)使用
//Registertransactiontimeout.
if(definition.getTimeout()!=TransactionDefinition.TIMEOUT_DEFAULT){
txObject.getSessionHolder().setTimeoutInSeconds(definition.getTimeout());//設(shè)置超時(shí)時(shí)間,如果其超時(shí)時(shí)間為-1,則不進(jìn)行設(shè)置,如果不是-1,那么超時(shí)時(shí)間是這樣設(shè)置的newDate(System.currentTimeMillis()+millis*1000);既程序員在配置文件中指定的其實(shí)是秒數(shù)
}
//RegistertheHibernateSession'sJDBCConnectionfortheDataSource,ifset.
if(getDataSource()!=null){
ConnectionHolderconHolder=newConnectionHolder(con);
if(definition.getTimeout()!=TransactionDefinition.TIMEOUT_DEFAULT){
conHolder.setTimeoutInSeconds(definition.getTimeout());
}
if(logger.isDebugEnabled()){
logger.debug("ExposingHibernatetransactionasJDBCtransaction["+con+"]");
}
TransactionSynchronizationManager.bindResource(getDataSource(),conHolder);
txObject.setConnectionHolder(conHolder);
}
//Bindthesessionholdertothethread.
if(txObject.isNewSessionHolder()){
TransactionSynchronizationManager.bindResource(getSessionFactory(),txObject.getSessionHolder());//如果是新的sessionholder則綁定到線程。這樣在進(jìn)入方法棧中的下一個(gè)方法時(shí)就能得到整個(gè)sessionholder了,connectionholder亦是如此
}
}
catch(Exceptionex){
SessionFactoryUtils.releaseSession(session,getSessionFactory());//如果拋出異常就釋放這個(gè)session,這個(gè)操作還會(huì)在后面出現(xiàn)
thrownewCannotCreateTransactionException("CouldnotopenHibernateSessionfortransaction",ex);
}
}
通過(guò)以上對(duì)代碼的注釋可以知道,如果給service設(shè)置聲明式事務(wù)管理,假設(shè)事務(wù)傳播途徑為required,然后一個(gè)service調(diào)用另一個(gè)service時(shí),他們其實(shí)是共用一個(gè)session,原則是沒(méi)有就創(chuàng)建,有就不創(chuàng)建,并返回之前已創(chuàng)建的session和transaction。也就是說(shuō)spring通過(guò)threadlocal把session和對(duì)應(yīng)的transaction放到線程之中,保證了在整個(gè)方法棧的任何一個(gè)地方都能得到同一個(gè)session和transaction。
所以如果你的方法在事務(wù)體之內(nèi),那么你只要通過(guò)hibernatesupportdao或者h(yuǎn)ibernatetemplate來(lái)得到session的話,那這個(gè)session一定是開(kāi)始事務(wù)的那個(gè)session,這個(gè)得到session的主要方法在SessionFactoryUtils里,我們來(lái)看一下
(這里還有一個(gè)小細(xì)節(jié),public abstract class SessionFactoryUtils ,Juergen Hoeller在寫(xiě)工具類(lèi)的時(shí)候?yàn)榱瞬荒茏屍溆袑?shí)例使用的是abstract,而我們一般的做法是final類(lèi)加private的構(gòu)造方法,看上去不怎么雅觀,看看源代碼還是能學(xué)習(xí)到不少寫(xiě)代碼的技巧的)
在SessionFactoryUtils的doGetSession里寫(xiě)到,如果當(dāng)前線程有綁定session,則返回這個(gè)session,如果沒(méi)有綁定session,則看是否允許創(chuàng)建(既allowCreate這個(gè)參數(shù)是true還是false,這個(gè)參數(shù)將會(huì)在很多地方設(shè)計(jì)到,比如說(shuō)hibernatetemplate和hibernatedaosupport里都有),如果不允許創(chuàng)建就拋出一個(gè)原始的hibernateException,舉個(gè)例子,如果你沒(méi)有給某個(gè)service方法配置聲明式事務(wù)管理,而卻要在這個(gè)service所調(diào)用的dao里得到當(dāng)前得session,這樣就會(huì)報(bào)這個(gè)錯(cuò)了:
代碼
if(method.getName().equals("getCurrentSession")){ |
【編輯推薦】