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
6
//
No existing transaction found -> check propagation behavior to find out how to behave.
7
if
(definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_MANDATORY)
{
8
throw
new
IllegalTransactionStateException(
9
"
Transaction propagation 'mandatory' but no existing transaction found
"
);
10
}
11
else
if
(definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_REQUIRED
||
12
definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_REQUIRES_NEW
||
13
definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_NESTED)
{
14
if
(debugEnabled)
{
15
logger.debug(
"
Creating new transaction with name [
"
+
definition.getName()
+
"
]
"
);
16
}
17
doBegin(transaction, definition);
18
boolean
newSynchronization
=
(
this
.transactionSynchronization
!=
SYNCHRONIZATION_NEVER);
19
return
newTransactionStatus(definition, transaction,
true
, newSynchronization, debugEnabled,
null
);
20
}
21
else
{
22
//
Create "empty" transaction: no actual transaction, but potentially synchronization.
23
boolean
newSynchronization
=
(
this
.transactionSynchronization
==
SYNCHRONIZATION_ALWAYS);
24
return
newTransactionStatus(definition,
null
,
false
, newSynchronization, debugEnabled,
null
);
25
}
26
2.当前有事务时
1
private
TransactionStatus handleExistingTransaction(
2
TransactionDefinition definition, Object transaction,
boolean
debugEnabled)
3
throws
TransactionException
{
4
5
if
(definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_NEVER)
{
6
throw
new
IllegalTransactionStateException(
7
"
Transaction propagation 'never' but existing transaction found
"
);
8
}
9
10
if
(definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_NOT_SUPPORTED)
{
11
if
(debugEnabled)
{
12
logger.debug(
"
Suspending current transaction
"
);
13
}
14
Object suspendedResources
=
suspend(transaction);
15
boolean
newSynchronization
=
(
this
.transactionSynchronization
==
SYNCHRONIZATION_ALWAYS);
16
return
newTransactionStatus(
17
definition,
null
,
false
, newSynchronization, debugEnabled, suspendedResources);
18
}
19
20
if
(definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_REQUIRES_NEW)
{
21
if
(debugEnabled)
{
22
logger.debug(
"
Suspending current transaction, creating new transaction with name [
"
+
23
definition.getName()
+
"
]
"
);
24
}
25
Object suspendedResources
=
suspend(transaction);
26
doBegin(transaction, definition);
27
boolean
newSynchronization
=
(
this
.transactionSynchronization
!=
SYNCHRONIZATION_NEVER);
28
return
newTransactionStatus(
29
definition, transaction,
true
, newSynchronization, debugEnabled, suspendedResources);
30
}
31
32
if
(definition.getPropagationBehavior()
==
TransactionDefinition.PROPAGATION_NESTED)
{
33
if
(
!
isNestedTransactionAllowed())
{
34
throw
new
NestedTransactionNotSupportedException(
35
"
Transaction manager does not allow nested transactions by default -
"
+
36
"
specify 'nestedTransactionAllowed' property with value 'true'
"
);
37
}
38
if
(debugEnabled)
{
39
logger.debug(
"
Creating nested transaction with name [
"
+
definition.getName()
+
"
]
"
);
40
}
41
if
(useSavepointForNestedTransaction())
{
42
//
Create savepoint within existing Spring-managed transaction,
43
//
through the SavepointManager API implemented by TransactionStatus.
44
//
Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
45
DefaultTransactionStatus status
=
46
newTransactionStatus(definition, transaction,
false
,
false
, debugEnabled,
null
);
47
status.createAndHoldSavepoint();
48
return
status;
49
}
50
else
{
51
//
Nested transaction through nested begin and commit/rollback calls.
52
//
Usually only for JTA: Spring synchronization might get activated here
53
//
in case of a pre-existing JTA transaction.
54
doBegin(transaction, definition);
55
boolean
newSynchronization
=
(
this
.transactionSynchronization
!=
SYNCHRONIZATION_NEVER);
56
return
newTransactionStatus(definition, transaction,
true
, newSynchronization, debugEnabled,
null
);
57
}
58
}
59
最后,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 的源代码
作者简介:
施祖阳,网名sylilzy,1979年生。
2002年起从事软件开发工作,主要研究为JAVA、Linux及相关技术。