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;
}
}