美文网首页spring framework
AopContext.currentProxy()解决同类中调用

AopContext.currentProxy()解决同类中调用

作者: markeNick | 来源:发表于2021-06-21 21:50 被阅读0次
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存入代理类

image-20210621154601726.png

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


image-20210621155326867.png

相关文章

  • AopContext.currentProxy()解决同类中调用

    如上代码,在同一个类中,非事务方法A调用事务方法B,会导致事务失效,可以采用AopContext.currentP...

  • AopContext.currentProxy()

    在同一个类中,非事务方法A调用事务方法B,事务失效,得采用AopContext.currentProxy().xx...

  • spring aop 同类中调用失败分析以及解决

    这是由于 Spring AOP (包括动态代理和 CGLIB 的 AOP) 的限制导致的.Spring AOP...

  • static 静态方法

    1.静态方法可以直接调用同类中的静态成员,不可以直接调用同类的费静态成员。 2.普通方法可以直接调用静态成员和非静...

  • static静态变量

    1、静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员,如果希望在静态方法中调用非静态变量,可以通过...

  • java面试知识总结--spring事务嵌套问题

    目的 分析spring的事务实际使用中的嵌套问题和场景 场景一 同类方法间调用,事务失效 效果: 结论一:同类方法...

  • 构造方法总结二

    构造器间的调用规则 指定构造器必须调用其直接父类的"指定构造器" 便利构造器必须调用同类中的其它构造器(指定或便利...

  • AopContext.currentProxy()

    aop 方法调用本地方法不起作用的时候用。

  • RPC的使用目的和如何实现

    RPC要解决的两个问题: 解决分布式系统中,服务之间的调用问题。 远程调用时,要能够像本地调用一样方便,让调用者感...

  • RPC总结

    RPC要解决的两个问题 解决分布式系统中,服务之间的调用问题。远程调用时,要能够像本地调用一样方便,让调用者感知不...

网友评论

    本文标题:AopContext.currentProxy()解决同类中调用

    本文链接:https://www.haomeiwen.com/subject/udeuyltx.html