posts - 29, comments - 0, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Spring 中的事务处理

Posted on 2007-05-28 15:33 change 阅读(171) 评论(0)  编辑  收藏

Spring 的声明式事务是通过TransactionProxyFactoryBean 来实现的,而它是通过持有一个拦截器:TransactionInterceptor 来做到的。

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);
 }

。。。。。。。。。。//声明的事务属性在这里得到                                   

                                       //见(DefaultTransactionDefinition)定义

}

//TransactionInterceptor 在service层的方法调用的时候,会更具配置判断调用的方法//是否需要事务的处理,若需要则获取设置事务属性对象和事务管理器并启动一个//事务,而其具体的实现是委托给 TransactionAspectSupport 类的//createTransactionIfNecessary 方法实现的,其类结构如下

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);//此处即是根据配置的声明性事务属性决定方法事务级别

  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 类方法createTransactionIfNecessary()里面根据配置的声明性事务属性,决定启动一个事务,和返回事务级别(信息):

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));

//此处的参数 this.transactionManager.getTransaction(transAtt) 即是调用各具体平台的 transactionManager 来获取她的事务属性,在获取事务属性的同时她会更具具体的事务属性 来决定是否开始和怎么开始一个事务;见类AbstractPlatformTransactionManager  结构。

 public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

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

public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {

if (isExistingTransaction(transaction)) {

//下面即是 更具具体的配置事务属性 来决定事务
   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 方法给更具具体的平台和配置事务属性来启动一个事务
    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;
 }

//下面是事务的提交操作,回滚类似

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

  //这里的transactionManager 就是Spring配置文件里面配置的事务 如: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  例,说说事务的开始和提交/回滚

//此dobegin()方法即是开始一个事务
 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

//此处即是真正的调用了hibernate的session开始一个事务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");
  }