spring的事务处理详解[原blog转载]

 

spring的事务处理详解[原blog转载]
注:此文为原blog转载过来,原文见:http://blog.sina.com.cn/sylilzy

[email protected] 施祖阳 http://hi.baidu.com/sylilzy
2008-6-16 11:47:16 星期一

spring的事务处理详解:调用一个方法后的事务处理过程

spring调用一个方法后的事务处理过程:
请参照TransactionInterceptor的invoke方法:
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;
}

调用目标方法时没有抛出异常时会调用:
doCommitTransactionAfterReturning(txInfo);
然后直接提交事务

如果抛异常则检查是否需要回滚事务(doCloseTransactionAfterThrowing方法会根据在spring中设备的Transaction Attribute),否则提交事务.

--------------------------------------

spring的事务处理详解:调用一个方法前的事务处理过程(源代码分析)


实际上,在spring的事务中,只要该类被设置为了事务代理:

拦截器都会创建一个TransactionInfo 对象:

TransactionInfo txInfo = new TransactionInfo(txAttr, method);


而且如果只要被调用的方法设置了事务属性(txAttr),不管是什么属性都会调用:

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

根据该方法的事务属性(definition )的不同,this.transactionManager.getTransaction(txAttr)的返回值会有所不同(代码见 AbstractPlatformTransactionManager),具体为以下几种情况:
1.当前没有事务时(即以下代码中的((HibernateTransactionObject) transaction).hasTransaction()返回false),会返回以下几种:

// Check definition settings for new transaction.
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
   throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}

// No existing transaction found -> check propagation behavior to find out how to behave.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
   throw new IllegalTransactionStateException(
     "Transaction propagation 'mandatory' but no existing transaction found");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
    definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
      definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
   if (debugEnabled) {
    logger.debug("Creating new transaction with name [" + definition.getName() + "]");
   }
   doBegin(transaction, definition);
   boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
   return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
}
else {
   // Create "empty" transaction: no actual transaction, but potentially synchronization.
   boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
   return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);
}

2.当前有事务时
private TransactionStatus handleExistingTransaction(
   TransactionDefinition definition, Object transaction, boolean debugEnabled)
   throws TransactionException {

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(
     definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
   if (debugEnabled) {
    logger.debug("Suspending current transaction, creating new transaction with name [" +
      definition.getName() + "]");
   }
   Object suspendedResources = suspend(transaction);
   doBegin(transaction, definition);
   boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
   return newTransactionStatus(
     definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
}

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
   if (!isNestedTransactionAllowed()) {
    throw new NestedTransactionNotSupportedException(
      "Transaction manager does not allow nested transactions by default - " +
      "specify 'nestedTransactionAllowed' property with value 'true'");
   }
   if (debugEnabled) {
    logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
   }
   if (useSavepointForNestedTransaction()) {
    // Create savepoint within existing Spring-managed transaction,
    // through the SavepointManager API implemented by TransactionStatus.
    // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
    DefaultTransactionStatus status =
      newTransactionStatus(definition, transaction, false, false, debugEnabled, null);
    status.createAndHoldSavepoint();
    return status;
   }
   else {
    // Nested transaction through nested begin and commit/rollback calls.
    // Usually only for JTA: Spring synchronization might get activated here
    // in case of a pre-existing JTA transaction.
    doBegin(transaction, definition);
    boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
    return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
   }
}

最后,txInfo被绑定到当前线程上作为当前事务:

txInfo.bindToThread()

然后,调用实际的目标类的方法并捕捉异常:

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


另外一点,TransactionInfo的newTransactionStatus调用时如果参数的不是null,TransactionInfo.hasTransaction()方法返回true;

重要提示:
在spring中创建的事务代理类并是目标类的超类,只是一个实现这目标类接口的类,该类会调用目标类的方法,所在如果一个目标类中的方法调用自身的另一个事务方法,另一个方法只是作为普通方法来调用,并不会加入事务机制
--------------------------------------------------------------------------------


spring的事务处理详解:事务创建


在配置spring的事务处理时,无论使用TransactionProxyFactoryBean,还是使用BeanNameAutoProxyCreator
spring的事务处理都是主要由TransactionInterceptor来拦截完成,此类扩展自org.aopalliance.intercept.MethodInterceptor,要查看spring的事务处理过程,首先要了解
TransactionInterceptor类的执行过程:


1.事务拦截器拦截调用方法:invoke();
2.调用TransactionAspectSupport的createTransactionIfNecessary,


createTransactionIfNecessary中:
首先创建TransactionInfo对象,然后
如果被调用的方法设置了事务属性(不管是什么属性,只要设置了),输出日志:

TransactionInterceptor 221 - Getting transaction for ...

并调用TransactionManager.getTransaction方法,

如果被调用的方法设置未设备事务,输出:Don't need to create transaction for ...

调用返回后然后将事务绑定到当前线程.createTransactionIfNecessary方法返回.

3.调用目标类的方法,并依次完成其它拦截器的调用
4.如果在上一步操作中有异常抛出,则会处理异常,处理过程:根据配置决定是提交还是回滚事务
5.如无异常,调用doFinally()将上一个事务(旧事务)设置为当前事务
4.调用doCommitTransactionAfterReturning提交事务,此为最重要的一步,与事务相关的操作在此实际生效.

调用TransactionManager.getTransaction过程 :
1.调用doGetTransaction()查找事务(此对象并不代表一个事务已经存在),返回的对象中包含事务的相关信息:如事务是否开始等.此对象将在以后作为doBegin and doCommit等方法的参数.

2.输出日志:
Using transaction object...
如:
HibernateTransactionManager 254 - Using transaction object...

3.调用isExistingTransaction(...)检查事务是否存在(是否已经开始一个事务),此方法为abstract方法,需要concreate类来实现,例如hibernate

4.如果isExistingTransaction为true,
如果是PROPAGATION_NEVER,则抛异常
PROPAGATION_NOT_SUPPORTED,则suspend当前事务并返回
PROPAGATION_REQUIRES_NEW,则suspend后创建一个新事务,
其它则
输出日志:"Participating in existing transaction"
然后
处理完后返回一个TransactionStatus对象,包含是否为新transaction,是否为新的newSynchronization,suspendedResources等,getTransaction()同时也返回

5.如果isExistingTransaction为false
检查超时是否小于默认时间,如果是则抛异常
如果当前方法的事务属性为PROPAGATION_MANDATORY,则抛异常,否则
如果当前方法的事务属性为PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED
输出日志:"Creating new transaction with name ..."
调用doBegin(...)创建并开始一个事务,然后返回
否则返回的return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);

--------------------------------------------------------------------------------

参考资料:
1.Spring Reference Manual:http://static.springframework.org/spring/docs/1.2.x/reference/index.html
2.Spring API doc:http://static.springframework.org/spring/docs/1.2.x/api/index.html

--------------------------------------------------------------------------------

作者简介:
    施祖阳,网名sylilzy,1979年生。
    2002年起从事软件开发工作,主要研究为JAVA、Linux及相关技术。
    你可通过[email protected] 与作者联系。

你可能感兴趣的:(spring的事务处理详解[原blog转载])