spring如何解决循环依赖的(精简版)

本文详细解释了Spring框架中如何通过三级缓存(一级、二级和三级)处理ServiceA和服务B的循环依赖问题,以及二级缓存的作用和AOP代理对象的生成策略。
摘要由CSDN通过智能技术生成
  1. 背景介绍
    大家都知道在ServiceA中依赖注入了ServiceB,ServiceB中又依赖注入了ServiceA,这就会出现循环依赖问题的,并且spring是通过三级缓存来解决循环依赖的问题的。
  2. 三级缓存介绍
    private final Map<String, Object> singletonObjects 一级缓存
    private final Map<String, Object> earlySingletonObjects 二级缓存
    private final Map<String, ObjectFactory<?>> singletonFactories 三级缓存
    ①一级缓存存储的是:单例Bean对象,完整的单例Bean对象,也就是说这个缓存中的Bean对象的属性都已经赋值了;是一个完整的Bean对象(已经赋值)!
    ②二级缓存存储的是:早期的单例Bean对象,这个缓存中的单例Bean对象的属性没有赋值,只是一个早期的实例对象(没有赋值)!
    ③三级缓存存储的是:单例工厂对象,这个里面存储了大量的“工厂对象”,每一个单例Bean对象都会对应一个单例工厂对象;这个集合中存储的是,创建该单例对象时对应的那个单例工厂对象。
  3. 三级缓存是如何发挥作用的
    还是以ServiceA中依赖注入了ServiceB,ServiceB中又依赖注入了ServiceA为例。
  • ServiceA在实例化之前会从一级缓存中拿,如果没有,则实例化,并且包装成ObjectFactory放到三级缓存中
  • ServiceA在依赖注入的时候发现了ServiceB,则会从一级缓存中拿,如果没有,则去实例化ServiceB,并且包装成ObjectFactory放到三级缓存中
  • ServiceB在依赖注入的时候又发现了ServiceA,然后会去一级缓存中拿,拿不到再去二级缓存中拿,二级缓存中拿不到,再去三级缓存中拿。拿到ServiceA的ObjectFactory之后,获取到半成品的bean对象放到二级缓存,并且删除三级缓存中ServiceA的ObjectFactory对象,返回返回这个bean,从而完成ServiceB中ServiceA的依赖注入
  • ServiceB依赖注入完成,进行初始化操作,完成之后把ServiceB放到一级缓存中,并且在二级缓存和三级缓存中清空ServiceB。至此ServiceB的创建工作完成。
  • ServiceA直接从一级缓存中拿到ServiceB,从而完成ServiceA中ServiceB的依赖注入,然后进行初始化操作,最后把ServiceA放到一级缓存中,并且清空二级缓存和三级缓存中ServiceA。至此ServiceA的创建工作完成。
  1. 可以不要二级缓存吗
    不行。假如还有一个ServiceC,ServiceA同时依赖了ServiceB和ServiceC,ServiceB依赖ServiceA,ServiceC依赖ServiceA。在ServiceB中依赖注入ServiceA的时候,会从三级缓存中拿到ObjectFactory对象,并且拿到对应的bean对象,然后删除三级缓存,并且放入二级缓存。假设这里没有二级缓存,那么当ServiceC在依赖注入ServiceA的时候,三级缓存中的ServiceA已经不存在了,也就没法注入ServiceA了,假设有二级缓存的话,这个地方可以直接从二级缓存中拿到ServiceA。所以这就是为什么需要二级缓存的原因。
  2. 可以不要三级缓存吗
    当然也是不行。因为在把对象提前暴露到三级缓存中的时候,如果这个对象需要aop,放到二级缓存中的对象就应该是它的代理对象,否则是普通对象。spring会判断这个需要aop的对象,是否存在循环依赖。如果存在循环依赖,在通过三级缓存把ObjectFactory生成的bean放到二级缓存中的过程,会生成它的代理对象放到二级缓存,否则会直接把的它原始对象放到耳机缓存。这也就是为什么只把这个对象的ObjectFactory对象放到三级缓存中的原因。
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值