Spring循环依赖

介绍

ABean创建-->依赖了B属性-->触发BBean创建--->B依赖了A属性--->需要ABean(但ABean还在 创建过程中)

@Service
public class A{
    @Autowire
    B b;
}

@Service
public class B{
    @Autowire
    A a;
}

解决方法

  • @Lazy注解:

    • 当发生循环依赖时,如果依赖注入需要一个Bean,并且这个Bean加了@Lazy注解,Spring容器会生成一个代理对象(Proxy)来模拟这个Bean的引用。这个代理对象并不是真正的Bean实例,而是一个占位符,它会在第一次被使用时,触发所代理的Bean的初始化。

    • 注意:@Lazy注解只能解决单例Bean之间的循环依赖问题,因为单例Bean在容器启动时就会被创建。对于原型(prototype)作用域的Bean,@Lazy注解不起作用,因为原型Bean每次获取时都会创建一个新的实例。

  • 三级缓存:

    • 详细分析:

      • 一级缓存:

        • 就是singletonObjects,是CourrentHashMap。

        • 缓存 经过完整生命周期 的bean。

      • 二级缓存:

        • 就是earlysingletonObject,是HashMap。

        • 缓存 未经完整生命周期 的bean。如果哪个bean出现了循环依赖,就会在推断构造方法后生成bean普通对象提前暴露存放到earlysingletonObjects,如果要进行AOP,就把代理对象存储到earlysingletonObjects,否则将原始对象存储到earlysingletonObjects,但不管怎么样,就算是代理对象,也是未经完整生命周期的代理对象,所以放入earlysingletonObjects我们会统称为 未经完全生命周期 的bean.

      • 三级缓存:

        • 就是singletonFactories,也是HashMap。

        • 缓存的是一个ObjectFactory,也就是一个Lambda表达式,在每个bean实例化之后,都会提前基于原始对象暴露一个Lambda表达式,并保存到三级缓存中,这个Lambda表达式 可能用到也可能用不到。没有出现循环依赖就用不到,就会按照正常的生命周期执行完,将对象存入到singletonObjects,如果出现了循环依赖,就会在依赖注入时到三级缓存中拿Lambda表达式,并执行Lambda表达式生成一个对象放到二级缓存中((如果当前Bean需要AOP,那么执行lambda表达式,得到就是对应的代理对象,如果无需AOP,则直接得到一个原始对象))。

      • 其实还要一个缓存,就是earlyProxyReferences,它用来记录某个原始对象是否进行过AOP。

    • 简单分析:

      • singletonObjects中缓存的是已经经历了完整生命周期的bean对象。

      • earlySingletonObjects比singletonObjects多了一个early,表示缓存的是早期的bean对象。早期是什么意思?表示Bean的生命周期还没走完就把这个Bean放入了earlySingletonObjects。

      • singletonFactories中缓存的是ObjectFactory,表示对象工厂,表示用来创建早期bean对象的工厂。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值