spring的事务处理详解

spring的事务处理详解[原blog转载]
2008-06-16 11:51

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

sylilzy@163.com 施祖阳 http://hi.baidu.com/sylilzy
2008-6-16 11:47:16 星期一

 

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

spring调用一个方法后的事务处理过程:
请参照TransactionInterceptor的invoke方法:

  1. try {
  2.    // This is an around advice.
  3.    // Invoke the next interceptor in the chain.
  4.    // This will normally result in a target object being invoked.
  5.    retVal = invocation.proceed();
  6. }
  7. catch (Throwable ex) {
  8.    // target invocation exception
  9.    doCloseTransactionAfterThrowing(txInfo, ex);
  10.    throw ex;
  11. }
  12. finally {
  13.    doFinally(txInfo);
  14. }
  15. doCommitTransactionAfterReturning(txInfo);
  16. return retVal;
  17. }

调用目标方法时没有抛出异常时会调用:
        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),会返回以下几种:

  1. // Check definition settings for new transaction.
  2. if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
  3.    throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
  4. }
  5. // No existing transaction found -> check propagation behavior to find out how to behave.
  6. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
  7.    throw new IllegalTransactionStateException(
  8.      "Transaction propagation 'mandatory' but no existing transaction found");
  9. }
  10. else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
  11.     definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
  12.       definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
  13.    if (debugEnabled) {
  14.     logger.debug("Creating new transaction with name [" + definition.getName() + "]");
  15.    }
  16.    doBegin(transaction, definition);
  17.    boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
  18.    return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
  19. }
  20. else {
  21.    // Create "empty" transaction: no actual transaction, but potentially synchronization.
  22.    boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
  23.    return newTransactionStatus(definition, nullfalse, newSynchronization, debugEnabled, null);
  24. }

2.当前有事务时

  1. private TransactionStatus handleExistingTransaction(
  2.    TransactionDefinition definition, Object transaction, boolean debugEnabled)
  3.    throws TransactionException {
  4. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
  5.    throw new IllegalTransactionStateException(
  6.      "Transaction propagation 'never' but existing transaction found");
  7. }
  8. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
  9.    if (debugEnabled) {
  10.     logger.debug("Suspending current transaction");
  11.    }
  12.    Object suspendedResources = suspend(transaction);
  13.    boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
  14.    return newTransactionStatus(
  15.      definition, nullfalse, newSynchronization, debugEnabled, suspendedResources);
  16. }
  17. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
  18.    if (debugEnabled) {
  19.     logger.debug("Suspending current transaction, creating new transaction with name [" +
  20.       definition.getName() + "]");
  21.    }
  22.    Object suspendedResources = suspend(transaction);
  23.    doBegin(transaction, definition);
  24.    boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
  25.    return newTransactionStatus(
  26.      definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
  27. }
  28. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
  29.    if (!isNestedTransactionAllowed()) {
  30.     throw new NestedTransactionNotSupportedException(
  31.       "Transaction manager does not allow nested transactions by default - " +
  32.       "specify 'nestedTransactionAllowed' property with value 'true'");
  33.    }
  34.    if (debugEnabled) {
  35.     logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
  36.    }
  37.    if (useSavepointForNestedTransaction()) {
  38.     // Create savepoint within existing Spring-managed transaction,
  39.     // through the SavepointManager API implemented by TransactionStatus.
  40.     // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
  41.     DefaultTransactionStatus status =
  42.       newTransactionStatus(definition, transaction, falsefalse, debugEnabled, null);
  43.     status.createAndHoldSavepoint();
  44.     return status;
  45.    }
  46.    else {
  47.     // Nested transaction through nested begin and commit/rollback calls.
  48.     // Usually only for JTA: Spring synchronization might get activated here
  49.     // in case of a pre-existing JTA transaction.
  50.     doBegin(transaction, definition);
  51.     boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
  52.     return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
  53.    }
  54. }

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

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

  1. try {
  2.    // This is an around advice.
  3.    // Invoke the next interceptor in the chain.
  4.    // This will normally result in a target object being invoked.
  5.    retVal = invocation.proceed();
  6. }
  7. catch (Throwable ex) {
  8.    // target invocation exception
  9.    doCloseTransactionAfterThrowing(txInfo, ex);
  10.    throw ex;
  11. }
  12. finally {
  13.    doFinally(txInfo);
  14. }
  15. doCommitTransactionAfterReturning(txInfo);
  16. return retVal;
  17. }

另外一点,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及相关技术。
    你可通过sylilzy@163.com与作者联系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值