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] 与作者联系。