dubbo + spring 服务端部分服务事务不起作用的原因

先抛出问题的原因:服务端的Service 出现了spring 的循环依赖

最近接手了一个项目,项目架构使用dubbo + spring frame 分模块进行开发。

假设有dubbo 消费端 A,服务端 B、C (B 和 C 在同一个项目),在开发过程中发现A 消费B 提供的服务,spring 事务不起作用。伪代码如下:

@Controller
class A {

    @Reference
    private B b;
    
    public void a() {

        b.insert(obj)
    }


}


@Service
@....dubbo...Service(interfacename = '...')
class B imp IB{
    @Transaction
    public void insert(obj) {
        dao.insert(obj);
        //do other
    }

}

@Service
class C imp IC{
    @Autowire
    private B b;
    
    @Transaction
    public void insert(obj) {
        b.insert(obj)
    }

}

在A 调用 B 的过程中,B 业务发生异常,但是事务并没有提交,通过多次单元测试,发现只有 A -> B 消费服务时才会出现事务失效的情况,而 C -> B 事务则正常,说明配置的事务实际上是有生效的,肯定是跟dubbo 整合的时候哪里出问题了。

思路:

1、查看dubbo 服务端中B 的对象 跟C 中注入的B 是不是同一个对象

通过跟踪代码,发现 AbstractProxyInvoker  中注入的B 的对象跟 C 中注入的不是同一个,因此肯定是Spring 初始化 Bean 的过程中,没有将动态代理之后的代理对象给dubbo 使用,而是给了一个最原始的实例。

2、跟踪Spring 在何时将 bean 的引用传给dubbo 的AbstractProxyInvoker

将断点打在下图中,对比:

证明思路1 是对的,然后往上跟踪代码,会走到 AnnotationBean  中的 postProcessAfterInitialization。

AnnotationBean 是dubbo 提供的一个BeanPostProcess,可以在bean 初始化完成之后,对bean 做一些增强。

那我们大致猜想,spring 在经过aop 代理生成之后的对象,传给dubbo 的 AnnotationBean ,然后注入到AbstractProxyInvoker,那么就跟踪下事务失效的这个类到底有没有被AOP 代理。

 3、将断点打在AOP 的核心类中 AbstractAutoProxyCreator,看下为什么传一个没有增强过的对象给dubbo。

可以看出,gameInfoServiceImpl,在这里走的是红色框住的代码,即没有被Aop 增强,那就原因就是 this.earlyProxyReferences.contains(cacheKey) ,接下来要去找下 earlyProxyReferences 在什么时候add bean name 的。

 

通过不管的回溯代码调用链,我们看到这样一行注释:

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.

表明了是为了解决循环依赖,才将beanName 先缓存到 earlyProxyReferences 这个容器中 。

至此,也就找到了事务不起作用的原因,只需要解决循环依赖即可。 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值