手写spring框架预备知识:三级缓存解决循环依赖问题

 本文讲解如何解决循环依赖,具体实现参考手写spring框架

1.为何会出现循环依赖

        A依赖B,同时B又依赖A,且两者都没有提前创建好,如下图所示:

        

 2.spring如何解决循环依赖

        打破循环的原理在出现循环的时候提前将其中的一个对象创建好,并注入到另一个对象。spring中采用的三级缓存的来实现这个操作,除了三级缓存外还需要一个set来判断是否出现循环依赖,那么在spring中创建对象的流程如下:

/**
     * 一级缓存,存放经过完整生命周期的单例bean对象
     */
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();

    /**
     * 二级缓存,存放提前进行aop代理的bean对象
     */
    private ConcurrentHashMap<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
    /**
     * 三级缓存,存放构造器创建的原始bean对象
     */
    private ConcurrentHashMap<String, Object> singletonFactories = new ConcurrentHashMap<>();
    /**
     * 记录正在创建中的bean,用于判断是否出现循环依赖
     */
    private Set<String> creatingSet = Collections.newSetFromMap(new ConcurrentHashMap<>());

         可能有眼尖的小伙伴就能看出来,二级缓存有什么用呢?spring为了保证单例的特性,会尽量保证对象在最后一步再进行Aop的动态代理操作,但是在出现循环依赖时就不得不提前进行Aop,此时就会出现两个问题:一是当A在正常流程注入B后需要进行Aop操作,此时如果A已经提前进行了Aop,就会出现B对象中的A和其他对象中的A对象不一样;二就是如果A在注入B后,还需要注入C对象,然而C对象也跟A出现循环依赖,那么此时A又需要提前Aop并且注入到C中,这样C对象中的A和B对象中的A就会出现不一致。为了避免上述情况的发送,spring会将提前Aop过的A对象放入二级缓存中,出现上述两种情况时会提前去二级缓存中查看是否有已经Aop过的A对象,保证对象的单例特性。最终流程如下:

3.项目地址 

        手写spring框架

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值