spring的事务处理详解:调用一个方法前的事务处理过程(源代码分析)
2006-09-08 09:33
1241 查看
实际上,在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中创建的事务代理类并是目标类的超类,只是一个实现这目标类接口的类,该类会调用目标类的方法,所在如果一个目标类中的方法调用自身的另一个事务方法,另一个方法只是作为普通方法来调用,并不会加入事务机制
参考资料:
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
3.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中创建的事务代理类并是目标类的超类,只是一个实现这目标类接口的类,该类会调用目标类的方法,所在如果一个目标类中的方法调用自身的另一个事务方法,另一个方法只是作为普通方法来调用,并不会加入事务机制
参考资料:
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
3.Spring 的源代码
相关文章推荐
- spring事务处理:调用一个方法前的事务处理过程
- Spring事务:调用同一个类中的方法
- spring 事务处理中,同一个类中:A方法(无事务)调B方法(有事务),事务不生效问题
- 基于SpringAOP的事务处理过程及原理分析
- 通过分析exevc系统调用处理过程来理解Linux内核如何装载和启动一个可执行程序
- 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。
- 详解基于spring多数据源动态调用及其事务处理
- Spring aop事务代理对象通过TransactionInterceptor处理目标方法事务过程,cglib方式
- 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为(转)
- java 分析方法调用过程
- spring方法内部调用方法事务关系
- hbase 源代码分析(6)get 过程 详解
- 转 业务层中 被调用服务的遭遇事务回滚的处理 2方法
- 若调用过程中仅中间方法使用了事务,那么真个调用过程是否使用了事务
- 通过分析system_call中断处理过程来深入理解系统调用
- jQuery源码分析之实例调用方法map,slice,first,last,end,sort,splice,push方法详解
- dotnet中调用存储过程的用法,包含事务处理
- 一个ArcGIS Javascript API的BUG和处理办法 - 调用两次Draw工具条deactivate方法导致的错误
- Liferay 部署war包中deployDirectory过程中调用updateWebXml()方法详细分析
- 在sql2000中,一个存储过程中调用另一个存储过程的实现方法