At the moment (spring-retry version < 2.0.1), by default the order is undefined as both advices for @Retryable
and @Transactional
annotations have order = Ordered.LOWEST_PRECEDENCE
.
It happens that RetryConfiguration
advice implements IntroductionAdvisor
interface. There is also method org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply
that adds into list all found advisors, but it does it using 2 consecutive loops: at first it adds all advisors that implement IntroductionAdvisor
interface and then all other avisors (this is why RetryConfiguration
advisor always happen to be before BeanFactoryTransactionAttributeSourceAdvisor
in this list). Then org.springframework.core.annotation.AnnotationAwareOrderComparator.sort
method is called, but because both advisors have the same order, the method keeps the order of advisors in the list.
So, basically, the reason why @Retryable
advisor is applied before @Transactional
advisor at the moment is just "by accident", or "implementation detail". It could be changed any moment by changing implementation of AopUtils.findAdvisorsThatCanApply
method or AnnotationAwareOrderComparator
etc. So, it's better to not rely on this implementation detail in your code. :)
Starting from spring-retry
version 2.0.1
(not released yet) there is new order
attribute of @EnableRetry
annotation that is equal to Ordered.LOWEST_PRECEDENCE - 1
by default to make sure @Retryable
advice will always be ordered before @Transactional
advice (when @Transactional
advice order is default).
The order
attribute could also be set to any other value, according to your needs, e.g. Ordered.LOWEST_PRECEDENCE - 4
.
@EnableRetry(order = Ordered.LOWEST_PRECEDENCE - 4)
@Configuration
public class MyAppConfiguration {}
With this configuration (and starting from spring-retry 2.0.1 - by default) the order of applying advices will be as this:
@Retryable
@Transactional
Your method body
End of @Transactional
End of @Retryable