Spring aop How to Switch Transactions by Getting Proxy Objects

  • 2021-11-01 03:29:35
  • OfStack

Spring aop Get Proxy Object for Transaction Switching

In a project, one method in the same class calls another method, and the transactions of the two methods are not related.

This involves a transaction switching problem, and the general method is no problem. According to the annotation identification on the method through aop annotation,

The answer is:

Get the proxy object of the current class through AopContext class in spring aop class,

In this way, you can switch the corresponding transaction manager as follows:

(1). Configure the following in the applicationContext. xml file:


<!--  Open exposure Aop Agent to ThreadLocal Support   -->  
    <aop:aspectj-autoproxy expose-proxy="true"/>  

(2). Get the proxy object where you need to switch,

Then call the corresponding method, as follows:


(( Class name ) AopContext.currentProxy()). Method ();  

(3). Attention

The method that needs to be used by the proxy object here must be a method of type public, otherwise the proxy object cannot be obtained, and the following error will be reported:

java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.

Open the exposed AOP agent.

Because of transaction opening and transaction rollback, the aop agent actually helps complete this process. When calling a method, it will first check when there is a transaction, and then open the transaction.

When a method of this class is called, it does not treat it as an proxy call, but rather as a direct call to the method, so there is no procedure to check whether the method contains a transaction,

Then the transaction called by the local method is invalid.

Get the original object of proxy bean


public class AopTargetUtil {
   /**
    *  Get   Target object 
    * @param proxy  Proxy object 
    * @return
    * @throws Exception
    */
   public static Object getTarget(Object proxy) throws Exception {
      if(!AopUtils.isAopProxy(proxy)) {
         return proxy;// Is not a proxy object 
      }
      if(AopUtils.isJdkDynamicProxy(proxy)) {
         return getJdkDynamicProxyTargetObject(proxy);
      } else { //cglib
         return getCglibProxyTargetObject(proxy);
      }
   }
   private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
      Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
      h.setAccessible(true);
      Object dynamicAdvisedInterceptor = h.get(proxy);
      Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
      advised.setAccessible(true);
      Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
      return target;
   }
   private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
      Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
      h.setAccessible(true);
      AopProxy aopProxy = (AopProxy) h.get(proxy);
      Field advised = aopProxy.getClass().getDeclaredField("advised");
      advised.setAccessible(true);
      Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
      return target;
   }
}

Related articles: