0
点赞
收藏
分享

微信扫一扫

AopContext.currentProxy()解决同类中调用嵌套方法AOP失效

奋斗De奶爸 2021-09-25 阅读 127
class Service {
    
    public void A() {
        // 调用本类其他方法,事务失效
        this.B();
    }
    
    @Transactional
    public void B() {
        
    }
}

如上代码,在同一个类中,非事务方法A调用事务方法B,会导致事务失效,可以采用AopContext.currentProxy().xxxxx()来保证事务生效。

无法切入的原因:

切入原理:创建代理类,在代理类中调用目标方法时进行切入。

上面代码,此时目标对象service,代理对象是Proxy_0,在同类Service中A方法调用B,本质是 this.B(),而不是Proxy_0.B()

其他解决办法

  • ApplicationContext.getBean()

  • 在本类中注入自己

  • 使用手动事务

注意事项:

Spring Boot需要在启动类加上以下注解

@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)

SSM需要xml文件配置

<aop:aspectj-autoproxy proxy-target-class="true"expose-proxy="true"/>

为什么AopContext可以解决同类方法AOP失效问题

AopContext类的源码如下

package org.springframework.aop.framework;

import org.springframework.core.NamedThreadLocal;
import org.springframework.lang.Nullable;

public final class AopContext {

    // 维护了一个ThreadLocal,存放AOP代理类
    private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");


    private AopContext() {
    }

    public static Object currentProxy() throws IllegalStateException {
        Object proxy = currentProxy.get();
        if (proxy == null) {
            throw new IllegalStateException(
                    "Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and " +
                            "ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.");
        }
        return proxy;
    }

    // 提供代理类set进ThreadLocal方法
    @Nullable
    static Object setCurrentProxy(@Nullable Object proxy) {
        Object old = currentProxy.get();
        if (proxy != null) {
            currentProxy.set(proxy);
        }
        else {
            currentProxy.remove();
        }
        return old;
    }

}

Spring中创建动态代理有两种方式

  • JDK动态代理

  • cglib动态代理

jdk动态代理创建时JdkDynamicAopProxy中的invoke方法中调用AopContext存入代理类

cglib动态代理CglibAopProxy在创建代理时也调用AopContext存入代理类


举报

相关推荐

AOP内部调用失效解决方案

0 条评论