6: Be careful, a flaw in springaop declarative transactions

Source: Internet
Author: User

[Problem]


Spring declarative events
I don't want to introduce it any more.
AOP, transaction management is really easy, really easy; Transaction Management Code is gone, the brain is gone, the hands are gone, all with transactions; lightweight, simple to test, hey! ". From which perspective
Look, lightweight declarative transactions are a great thing to free up productivity. Therefore, we always use it ".

 

However, in a recent project, we encountered a transaction management problem: there is a service class, one of which declares the transaction method, which performs three insert SQL operations, however, when a rollback error occurs later, we find that the previous insertion is successful. That is to say, this declares the transaction method,The transaction is not actually started.
! What's going on? Is spring declarative transactions invalid?

 

[Exploring]

In fact, some people may say that the Spring transaction configuration does not work, but according to the first response and past experience, I will always tell him that your configuration is wrong; so this time, I think it will not be an exception, it is probably to take the transaction
Annotations are configured on interfaces rather than implementation methods.
Or, if it is declared in XML format, it is likely that the expression of the starting point is not paired.

 

However, after checking their configurations, we found that there was no configuration problem. The @ transactional transaction annotation declaration was used for the implementation method of the transaction, the annotation driver is also configured in XML <TX: annotation-driven... />. The configuration is correct. How can it not work?

 

I was wondering, so I asked:

Q 1: Is this the case with other methods?

Answer 1: No.

Question 2: Is there anything special about this method (method B )?

Answer 2: three records are inserted in the background, which is nothing special.

Question 3: Is this method called directly from the web layer?

Answer 3: No, yesThis service class
(Servicea)Another method called
(Method ).

Q 4: Oh, is the method for calling it matched with a transaction (the problem may be )?

Answer 4: No.

Question 5: The Web layer action (using struts2) callsNo way to declare a transaction
, Method A is called againDeclared transaction method B
?

Answer 5: Yes.

Question 6: add the transaction Statement on method.

Answer 6: Okay...

It seems that the problem is located, so add @ transactional to method A and start the project test. The result is:The transaction takes effect normally.
Method A and method B are in a transaction.

 

Now, let's summarize the phenomenon:

1. servicea class is a Web-layer Action Service

2. Action calls servicea's method A, but method A does not declare a transaction (because method A itself is time-consuming and does not need a transaction)

3. servicea method A calls its own method B, while Method B declares the transaction, but the transaction Statement of Method B fails in this case.

4. If a transaction is declared on method A, the transaction takes effect when action calls method A, and method B automatically participates in the transaction.
 

 

I asked him to add a and the transaction statement, and I decided to come back and test it again.

 


On the surface, this problem is caused by the failure of the transaction statement. In fact, it may be caused by the implementation of spring's AOP mechanism. I think of one that I found a long time ago when I studied spring's AOP implementation.
Symptom: For the AOP target class enhanced in cglib mode, two objects are created, one for bean instance itself and the other for cglib enhanced proxy object, not just the latter. I used
I had doubts about this, but I didn't go into it again.

 

We know that spring has two AOP implementation methods: 1. Java proxy; 2. cglib dynamic enhancement. These two methods can be seamlessly and freely switched in spring. The advantage of Java proxy mode is that it does not rely on third-party jar packages. The disadvantage is that it cannot be used as a proxy class and can only be used as a proxy interface.

 

Spring abstracts these two implementations through the aopproxy interface and implements the same AOP method:

 

 

 

It seems that this abstraction also has a defect, that is, the ability of cglib to directly create enhancement subclasses of common classes is eliminated. Spring is equivalent to dynamically generating subclasses of cglib, when the common proxy class is used, this is why two objects are created. Shows the actual call process of spring's AOP proxy class:

 

 

 

Therefore, from the above analysis, we can see that methodb is not notified by aopproxy, and the final result is:Enhancement notifications on the called methods of classes reinforced by Spring AOP do not work when calling internal methods of the same class.
.

 

What is the impact of such a result:

1: The transaction statement of the called method does not work during internal calls.

2: in other words, when you declare a method that requires transactions, if there are other developers in this class, you cannot guarantee that this method will actually be in the transaction environment.

3: in other words,Spring's transaction Propagation Policy does not work during internal method calls.
. Whether you want a method to require a separate transaction, requiresnew, nested transaction, nested, or so on, it doesn't work.

4: not only transaction notifications, but all AOP notifications that you implement using spring will be subject to the same restrictions ....

 

[Solution]

 

The cause of the problem has been found. In fact, the ideal AOP implementation should be as follows:

 

 

As long as a cglib enhancement object is needed, I will not hesitate to discard the Java proxy method.

 

As for the previous transaction problem, we only need to avoid the restrictions on Spring's current AOP implementation, either declare a transaction, split it into two classes, or directly use a programmatic transaction in the method, so everything is OK.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.