Analysis of the principle of spring transaction failure caused by spring AOP dynamic proxy mechanism

First two pictures, students who understand the pictures can stop reading.

 

  Let's talk about the problem here. A class in the service layer of springMVC provides multiple methods, a(), b(), c(), d(). Among them, the transaction declaration (@Transactional) is not displayed on the method a, and the transaction declaration is displayed in the methods b(), c(), and d(). And there is no problem with spring's annotation scanning and bean instantiation process (excluding the impact of other problems).

  At this time, the controller layer calls the method a() using this service object, and the processing logic is a()->b()->c()->d(), which has such a calling relationship. The result is that this call from method a does not add a transaction.

  Yes, it is a bit strange at first glance, but after careful analysis, it becomes clear.

  This also has to start with the implementation principle of spring AOP. Spring AOP is implemented based on dynamic proxy. It is divided into two types: jdk and cglib. In short, jdk can only proxy for interfaces, and cglib can proxy for common classes. Transactions are implemented through proxy classes. When an annotated class is dynamically proxied, all methods of calling objects of this class are to execute the open transaction of the proxy class first (if a transaction is added to this method), Then enter the proxied object to execute the corresponding method. However, when the method in this object is called in the proxied object, it will not be executed through the proxy class (as shown in Figure 1 above). Since the transaction is completed through the proxy class, if the parent call is not enabled, the subsequent method call is Transactions will no longer be opened. In the above example, method a does not declare a transaction, so there is no transaction for method a in the proxy class. After entering the proxied system, methods b, c, and d are called. Although there are transaction annotations on methods b, c, and d, because they are The internal method call of the original proxy class did not return the proxy class to start the transaction. Story task "failed".

  Figure 2 is an ideal usage. You can get the proxy class of the current class through AopContext.currentProxy(); in the proxy class, and then continue to execute the corresponding transactional method from the proxy class.

 

 

  PS Today is a day to remember. There was a transaction problem in the production environment of a project. On this issue, I lost my pk. My boss is also the technical boss of our department. Worked for less than 3 years, proud of myself.

  

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324693994&siteId=291194637