Annotation-based and xml-based transaction definitions precedence
I couldn't find a definitive answer to this in the docs, and although there seems to be a logical answer, one can't be sure. The scenario is this - you have a xml-based transaction definition, like:
<tx:advice id="txAdvice" transaction-manager="jpaTransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
Which advises all service methods. But then you have @Transactional
on a concrete class/method, where you want to override the propagation
attribute.
It is clear that @Transactional
at method-level overrides the same one at class-level, but does it override the开发者_运维问答 <tx:advice>
(and actually, the <aop:pointcut>
)?
I hope two interceptors won't be created on the same class, (and whichever happens to be first will start the transaction)
Thanks to skaffman for his effort. Finally I think I got the behaviour:
- Both
<aop:advisor>
and@Transactional
(together with<tx:annotation-driven>
) create aTransactionInterceptor
around the target class (the one, whose methods are to be run in transaction). - The advice with a lower
order
attribute overrides the other one. If no order attribute is specified, the order is undefined. But my tests showed that the one defined latest in theapplicationContext.xml
takes precedence, although this might not be the case always:
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined.
At least this is the behaviour for spring 2.5.6.
After a bit of digging, I think the answer lies in TxAdviceBeanDefinitionParser.doParse
. The logic says:
if <tx:attributes> is present then
parse <tx:attributes>
else
instantiate an AnnotationTransactionAttributeSource to determine TX attributes
Given the only thing that reads @Transactional
is AnnotationTransactionAttributeSource
, that strongly suggests to me that <tx:advice>
will consult @Transactional
if and only if <tx:attributes>
is not specified, so no overriding is possible.
This does seem to contradict Spring's usual "principle of least surprise" approach, since like you I would have expected the annotation to take precedence on a per-class or per-method basis. I would file an issue on their JIRA to get this behaviour changed.
Having said all that, I still think it's worth giving this a try to see what it does, since it may work by some other mechanism.
精彩评论