自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring聲明式事務(wù)管理源碼解讀之事務(wù)開(kāi)始

開(kāi)發(fā) 后端
事務(wù)是所有企業(yè)應(yīng)用系統(tǒng)的核心,之前人們使用EJB的時(shí)候,容器事務(wù)管理(CMT),是SLSB最令人稱道的地方,據(jù)說(shuō)很多人使用EJB,使用SLSB就是為了CMT,但是spring出現(xiàn)之后,格局就變了,因?yàn)槌绦騿T又多了一種選擇,就是聲明式事務(wù)管理,聲明式事務(wù)管理是基于AOP的,及AOP是它的底層特性,本文的目的就是為了和大家探討一下spring的聲明式事務(wù)管理,從源代碼來(lá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.  
  *

Thisistypicallythedefaultsettingofatransactiondefinition.     */    intPROPAGATION_REQUIRED=0;

當(dāng)然其中也定義了隔離級(jí)別

/**

代碼

*Aconstantindicatingthatdirtyreadsareprevented;non-repeatablereads  
*andphantomreadscanoccur.Thislevelonlyprohibitsatransaction  
*fromreadingarowwithuncommittedchangesinit.  
*@seejava.sql.Connection#TRANSACTION_READ_COMMITTED  
*/  
intISOLATION_READ_COMMITTED =Connection.TRANSACTION_READ_COMMITTED; 

同時(shí)還有兩個(gè)對(duì)應(yīng)的方法來(lái)得到這樣的傳播途徑和隔離級(jí)別

代碼

/**  
  *Returnthepropagationbehavior.  
  *MustreturnoneofthePROPAGATIONconstants.  
  *@see#PROPAGATION_REQUIRED  
  *@seeorg.springframework.transaction.support.TransactionSynchronization
Manager#isActualTransactionActive()  
  */ 
  intgetPropagationBehavior();  
  /**  
  *Returntheisolationlevel.  
  *MustreturnoneoftheISOLATIONconstants.  
  *

OnlymakessenseincombinationwithPROPAGATION_REQUIREDor  
  *PROPAGATION_REQUIRES_NEW.  
  *

Notethatatransactionmanagerthatdoesnotsupportcustom  
  *isolationlevelswillthrowanexceptionwhengivenanyotherlevel  
  *thanISOLATION_DEFAULT.  
  *@see#ISOLATION_DEFAULT  
  */ 
  intgetIsolationLevel();  

這個(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方法:

代碼

//Workoutthetargetclass:maybenull.  
    //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方法:

代碼

publicfinalTransactionStatusgetTransaction(TransactionDefinitiondefinition)throwsTransactionException{  
    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()      thrownewInvalidTimeoutException("Invalidtransactiontimeout",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í)例

代碼

txObject.getSessionHolder().setSynchronizedWithTransaction(true);  
      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")){  
        //HandlegetCurrentSessionmethod:returntransactionalSession,ifany.  
        try{  
          returnSessionFactoryUtils.doGetSession((SessionFactory)proxy,false);  
//***一個(gè)參數(shù)是false,說(shuō)明這個(gè)方法不能返回一個(gè)新的session,沒(méi)有就拋異常  
        }  
        catch(IllegalStateExceptionex){  
          thrownewHibernateException(ex.getMessage());  
        }  
      }  

【編輯推薦】

  1. Spring聲明式事務(wù)管理源碼解讀之事務(wù)提交
  2. Spring中XML配置的12個(gè)技巧
  3. Spring MVC框架的高級(jí)配置
  4. 如何在Java Web應(yīng)用中獲取Spring的ApplicationContext
責(zé)任編輯:楊鵬飛 來(lái)源: javaeye
相關(guān)推薦

2009-02-11 13:08:29

事務(wù)提交事務(wù)管理Spring

2024-11-13 19:03:14

2009-06-22 09:01:57

Spring聲明式事務(wù)

2023-10-08 08:28:10

Spring事務(wù)管理

2009-06-17 14:57:11

Spring事務(wù)管理

2009-06-30 16:57:42

Spring事務(wù)管理

2023-03-27 10:40:09

2009-06-08 17:56:00

SpringJDBC事務(wù)

2014-08-25 09:12:47

Spring事務(wù)管理

2023-05-06 07:29:49

Spring事務(wù)傳播

2010-03-29 13:34:15

ibmdwSpring

2009-09-25 12:59:53

Hibernate事務(wù)

2010-03-23 08:46:40

Spring

2021-09-06 13:42:14

Spring聲明式事務(wù)

2009-06-17 14:43:47

Spring框架Spring事務(wù)管理

2025-02-08 10:56:18

2009-06-03 10:20:11

Hibernate事務(wù)管理配置

2023-04-28 08:21:36

SpringBoot聲明式事務(wù)編程式事務(wù)

2009-09-29 09:44:52

Hibernate事務(wù)

2009-09-23 17:48:00

Hibernate事務(wù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)