Custom Spring AOP Around + @Transactional

I have custom Around implemented according to user annotation. I want the user interface to execute WITHIN in an external @Transactional. Unfortunately this does not work. (AOP works. I see stacks that show it).

The stack trace shows my AOP execution before (logger), the MyBatis session starting the transaction, MyBatis closing the transaction, Spring closing the transaction, and then completing my AOP.

I thought helping my support for AOP Ordered would help. I set the value returned to 1. I used. This did not work. I think this is because I misunderstood how Spring orders.

Order

What happens when a few tips everyone wants to work on the same connection point? Spring AOP follows the same priority rules as AspectJ to determine the order in which recommendations are followed. The highest priority advice starts first "on the way to" (so two pieces are given before the advice, the first with the highest priority is launched first). "To exit the junction point, the last seniority council works last (so two pieces are given after the consultation, the second will be performed with the highest priority).

When two tips, defined in different aspects, should be executed at the same connection point, unless you specify otherwise the order of execution is undefined. You can control the execution order by specifying priority. This is done in the usual way in Spring by implementing the org.springframework.core.Ordered interface in a class or annotating it with an order annotation. Given two aspects, an aspect returning a lower value from Ordered.getValue () (or the value of the annotation) takes precedence.

When two pieces of advice, defined in the same aspect, must be executed at the same join point, the order is undefined (since there is no way to get order declarations through reflection for javac-compiled classes). Consider breaking down such consultation methods into one recommendation method per connection point in each class of classes or refactoring tips for individual aspect classes - which can be ordered at the aspect level.

So, I took the order attribute. This should force @Transactional to return Integer.MIN_VALUE. Therefore, if I understood the above quote, I should have worked last. When I redistribute, it is still running backward. My AOP, Spring TX, MyBatis, Close MyBatis, Close Spring Tx, Close my AOP.

What am I doing wrong?

+6
source share
3 answers

If the order attribute is not configured for the @Transactional annotation, the Advisor that is responsible for the transaction attribute - AbstractPointcutAdvisor (in fact, one of the subclasses) will return Ordered .LOWEST_PRECEDENCE, which is defined as Integer.MAX_VALUE.

The adviser responsible for the AOP user advice, a subclass of the same AbstractPointcutAdvisor, will see if the actual Advice implements the ordered interface, and if so, the provided value will be used for sorting. If the AOP user tip does not implement a custom interface, the EA returns the same default Ordered.LOWEST_PRECEDENCE, and the sorting result becomes slightly unpredictable.

So, setting the order attribute for the @Transactional annotation, for example. like this

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd> ....... <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="[Order for @Transactional]"> <beans/> 

and your custom implementation of AOP recommendations looks like this:

 import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.core.Ordered; @Aspect public class CustomAspect implements Ordered { @Around(value = "@annotation(CustomAnnotation)") public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { ... } .... @Override public int getOrder() { return [Order for @CustomAnnotation]; } .... } 

then you probably have all the freedom (but statically) with ordering throughout the application.

Under the hood is AspectJAwareAdvisorAutoProxyCreator , which on Proxy Initialization sorts Advisors using the org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator comparator, which delegates the OrderComparator sort. Later, after the actual execution, a specific implementation of AopProxy is executed for a specific method, an array of tips, which it calls interceptors, and this can be used to dynamically reorder, I think, but none of these things seem easily accessible and / or customizable to me.

My environment is Spring Beans, TX, AOP - all version 4.0.3. I also have two custom transaction managers, one related to Hibernate and one related to JDBC DataSource-bound, but I don't think it matters here.

+7
source

After a little experiment, it turns out that just removing the order attribute doesn't do the job. I find this odd since the @Transactional order by default is Integer.MIN_VALUE . Apparently, if you want to include an order, you need to explicitly specify the order for the smallest of all AOP orders.

+3
source

The https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html page says that the default transaction order is Ordered.LOWEST_PRECEDENCE , whose value is Integer.MAX_VALUE

+2
source

All Articles