posts - 29, comments - 0, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          Spring 中的事務(wù)處理

          Posted on 2007-05-28 15:33 change 閱讀(174) 評(píng)論(0)  編輯  收藏

          Spring 的聲明式事務(wù)是通過(guò)TransactionProxyFactoryBean 來(lái)實(shí)現(xiàn)的,而它是通過(guò)持有一個(gè)攔截器:TransactionInterceptor 來(lái)做到的。

          public class TransactionProxyFactoryBean extends ProxyConfig implements FactoryBean, InitializingBean {

           private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();

           /**
            * Set the transaction manager. This will perform actual
            * transaction management: This class is just a way of invoking it.
            * @see TransactionInterceptor#setTransactionManager
            */
           public void setTransactionManager(PlatformTransactionManager transactionManager) {
            this.transactionInterceptor.setTransactionManager( transactionManager);
           }

          。。。。。。。。。。//聲明的事務(wù)屬性在這里得到                                   

                                                 //見(jiàn)(DefaultTransactionDefinition)定義

          }

          //TransactionInterceptor 在service層的方法調(diào)用的時(shí)候,會(huì)更具配置判斷調(diào)用的方法//是否需要事務(wù)的處理,若需要?jiǎng)t獲取設(shè)置事務(wù)屬性對(duì)象和事務(wù)管理器并啟動(dòng)一個(gè)//事務(wù),而其具體的實(shí)現(xiàn)是委托給 TransactionAspectSupport 類(lèi)的//createTransactionIfNecessary 方法實(shí)現(xiàn)的,其類(lèi)結(jié)構(gòu)如下

          public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor {

           public Object invoke(MethodInvocation invocation) throws Throwable {
            // Work out the target class: may be null.
            // The TransactionAttributeSource should be passed the target class
            // as well as the method, which may be from an interface
            Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;
            
            // Create transaction if necessary
            TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);//此處即是根據(jù)配置的聲明性事務(wù)屬性決定方法事務(wù)級(jí)別

            Object retVal = null;
            try {
             // This is an around advice.
             // Invoke the next interceptor in the chain.
             // This will normally result in a target object being invoked.
             retVal = invocation.proceed();
            }
            catch (Throwable ex) {
             // target invocation exception
             doCloseTransactionAfterThrowing(txInfo, ex);
             throw ex;
            }
            finally {
             doFinally(txInfo);
            }
            doCommitTransactionAfterReturning(txInfo);

            return retVal;
           }
           
          }

          //在TransactionAspectSupport 類(lèi)方法createTransactionIfNecessary()里面根據(jù)配置的聲明性事務(wù)屬性,決定啟動(dòng)一個(gè)事務(wù),和返回事務(wù)級(jí)別(信息):

          protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {
            // If the transaction attribute is null, the method is non-transactional
            TransactionAttribute transAtt = this.transactionAttributeSource.getTransactionAttribute(method, targetClass);
            TransactionInfo txInfo = new TransactionInfo(transAtt, method);
            if (transAtt != null) {
             // We need a transaction for this method
             if (logger.isDebugEnabled()) {
              logger.debug("Getting transaction for " + txInfo.joinpointIdentification());
             }

             // The transaction manager will flag an error if an incompatible tx already exists

             txInfo.newTransactionStatus(this.transactionManager.getTransaction(transAtt));

          //此處的參數(shù) this.transactionManager.getTransaction(transAtt) 即是調(diào)用各具體平臺(tái)的 transactionManager 來(lái)獲取她的事務(wù)屬性,在獲取事務(wù)屬性的同時(shí)她會(huì)更具具體的事務(wù)屬性 來(lái)決定是否開(kāi)始和怎么開(kāi)始一個(gè)事務(wù);見(jiàn)類(lèi)AbstractPlatformTransactionManager  結(jié)構(gòu)。

           public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

          。。。。。。。。。。。。。。。。。。。。。

          public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {

          if (isExistingTransaction(transaction)) {

          //下面即是 更具具體的配置事務(wù)屬性 來(lái)決定事務(wù)
             if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER)
          {
              throw new IllegalTransactionStateException(
                "Transaction propagation 'never' but existing transaction found");
             }
             if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
              if (debugEnabled) {
               logger.debug("Suspending current transaction");
              }
              Object suspendedResources = suspend(transaction);
              boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
              return newTransactionStatus(
                null, false, newSynchronization, definition.isReadOnly(), debugEnabled, suspendedResources);
             }
             else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
              if (debugEnabled) {
               logger.debug("Creating new transaction, suspending current one");
              }
              Object suspendedResources = suspend(transaction);

          //此處的doBegin 方法給更具具體的平臺(tái)和配置事務(wù)屬性來(lái)啟動(dòng)一個(gè)事務(wù)
              doBegin(transaction, definition);
              boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
              return newTransactionStatus(
                transaction, true, newSynchronization, definition.isReadOnly(), debugEnabled, suspendedResources);
             }

          。。。。。。。。。。。。。。。。。。。。。

          }

            // We always bind the TransactionInfo to the thread, even if
            // we didn't create a new transaction here.
            // This guarantees that the TransactionInfo stack will be
            // managed correctly even if no transaction was created by
            // this aspect.
            txInfo.bindToThread();
            return txInfo;
           }

          //下面是事務(wù)的提交操作,回滾類(lèi)似

          protected void doCommitTransactionAfterReturning(TransactionInfo txInfo) {
            if (txInfo != null && txInfo.hasTransaction()) {
             if (logger.isDebugEnabled()) {
              logger.debug("Invoking commit for transaction on " + txInfo.joinpointIdentification());
             }

            //這里的transactionManager 就是Spring配置文件里面配置的事務(wù) 如:org.springframework.orm.hibernate3.HibernateTransactionManager 。
             this.transactionManager.commit(txInfo.getTransactionStatus());

            }
           }

          //

          protected void doFinally(TransactionInfo txInfo) {
            if (txInfo != null) {
             txInfo.restoreThreadLocalStatus();
            }
           }
          private void restoreThreadLocalStatus() {
             // Use stack to restore old transaction TransactionInfo.
             // Will be null if none was set.
             currentTransactionInfo.set(oldTransactionInfo);
            }

          //下面以 HibernateTransactionManager  例,說(shuō)說(shuō)事務(wù)的開(kāi)始和提交/回滾

          //此dobegin()方法即是開(kāi)始一個(gè)事務(wù)
           protected void doBegin(Object transaction, TransactionDefinition definition) {
            HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;

            if (txObject.getSessionHolder() == null) {
             Session session = SessionFactoryUtils.getSession(
               getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator(), false);
             if (logger.isDebugEnabled()) {
              logger.debug("Opened new session [" + session + "] for Hibernate transaction");
             }
             txObject.setSessionHolder(new SessionHolder(session), true);
            }

            txObject.getSessionHolder().setSynchronizedWithTransaction(true);
            Session session = txObject.getSessionHolder().getSession();

            try {
             Connection con = session.connection();
             Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
             txObject.setPreviousIsolationLevel(previousIsolationLevel);

             if (definition.isReadOnly() && txObject.isNewSessionHolder()) {
              // just set to NEVER in case of a new Session for this transaction
              session.setFlushMode(FlushMode.NEVER);
             }

             if (!definition.isReadOnly() && !txObject.isNewSessionHolder()) {
              // we need AUTO or COMMIT for a non-read-only transaction
              FlushMode flushMode = session.getFlushMode();
              if (FlushMode.NEVER.equals(flushMode)) {
               session.setFlushMode(FlushMode.AUTO);
               txObject.getSessionHolder().setPreviousFlushMode(flushMode);
              }
             }

             // add the Hibernate transaction to the session holder

          //此處即是真正的調(diào)用了hibernate的session開(kāi)始一個(gè)事務(wù)session.beginTransaction() 。
             txObject.getSessionHolder().setTransaction(session.beginTransaction());

             // register transaction timeout
             if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {
              txObject.getSessionHolder().setTimeoutInSeconds(definition.getTimeout());
             }

             // register the Hibernate Session's JDBC Connection for the DataSource, if set
             if (getDataSource() != null) {
              ConnectionHolder conHolder = new ConnectionHolder(con);
              if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {
               conHolder.setTimeoutInSeconds(definition.getTimeout());
              }
              if (logger.isDebugEnabled()) {
               logger.debug("Exposing Hibernate transaction as JDBC transaction [" +
                 conHolder.getConnection() + "]");
              }
              TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
              txObject.setConnectionHolder(conHolder);
             }

             // bind the session holder to the thread
             if (txObject.isNewSessionHolder()) {
              TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
             }
            }

            catch (Exception ex) {
             SessionFactoryUtils.closeSessionIfNecessary(session, getSessionFactory());
             throw new CannotCreateTransactionException("Could not create Hibernate transaction", ex);
            }
           }

          //回滾

          protected void doCommit(DefaultTransactionStatus status) {
            HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();

          。。。。。。。。。。。。。。。。。。。。。。。。。。
            try {
             txObject.getSessionHolder().getTransaction().commit();
            }
            catch (net.sf.hibernate.TransactionException ex) {
             // assumably from commit call to the underlying JDBC connection
             throw new TransactionSystemException("Could not commit Hibernate transaction", ex);
            }
            catch (JDBCException ex) {
             // assumably failed to flush changes to database
             throw convertJdbcAccessException(ex.getSQLException());
            }
            catch (HibernateException ex) {
             // assumably failed to flush changes to database
             throw convertHibernateAccessException(ex);
            }
           }

            }
            else {
             // The TransactionInfo.hasTransaction() method will return
             // false. We created it only to preserve the integrity of
             // the ThreadLocal stack maintained in this class.
             if (logger.isDebugEnabled())
              logger.debug("Don't need to create transaction for " + methodIdentification(method) +
                ": this method isn't transactional");
            }
          主站蜘蛛池模板: 额敏县| 稻城县| 图木舒克市| 建昌县| 建瓯市| 天长市| 安多县| 扎鲁特旗| 扎囊县| 鞍山市| 中方县| 阿勒泰市| 洞头县| 济阳县| 凭祥市| 南郑县| 曲周县| 周口市| 色达县| 翁源县| 南靖县| 马鞍山市| 莱西市| 肃宁县| 永胜县| 禹州市| 剑阁县| 长垣县| 安徽省| 遵义县| 克什克腾旗| 西青区| 余庆县| 塘沽区| 吉安市| 新宁县| 巴塘县| 油尖旺区| 黄冈市| 保康县| 潜江市|