三级循环解决循环依赖

三级循环解决循环依赖

首先我们要理解什么是依赖缓存?

简单来说,假如这里有两个类:AService 和 BService 两个Bean对象。并且做测试方法

@Component
public class AService{
    @Autowire
    private BService bService;
    public void test(){
        System.out.println(bService);
    }
}

@Component
public class BService{
    @Autowire
    private AService aService;
}

public class Test{
    public static void main(String[] args) {
        // 这里new了一个Spring容器出来
        AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(AppConfig.class);
        // 然后从容器中获取Bean对象出来
        AService aService = (AService)application.getBean("AService");
        // 然后执行Bean对象的方法
        aService.test();
    }
}

这里我们需要注意就是为什么可以从Spring获取到这个Bean对象出来呢?

img

想要获得AService的完整Bean对象,就需要填充BService的属性,此时AService就会去单例池(一级缓存)中去寻找BService的Bean对象出来给AService赋值。发现,单例池中没有BService的Bean对象,所以就需要去创建BService的Bean对象。BService也需要像AService一样执行上图的实例化操作。那么获得BService对象后,发现单例池也没有AService对象。难道又需要去创建AService对象执行上图操作吗?以上描述就是 循环依赖。(图片流程如下图)

img[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vP4zQija-1672237936849)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

那么如何解决这个循环依赖问题?

先放出一个完整的流程图

img

单例池的效果(ConcurrentHashMap)?

就是你在需要在获取Spring容器里面的一个对象的时候获取到的Bean对象是同一个,你比如说输入的是 容器.getBean("AService"); ,你将获取到的永远是同一个Bean对象。这就是所谓的单例池的作用。

同时我们要知道,代理对象中肯定是有个属性指向这个普通对象的

扩展:啥情况的循环依赖是Spring不能解决呢?

假如上面的AService和BService中没有假如@Autowire注解,那么就不能用Spring解决了。(可以假如**@lazy**注解实现)

@Component
public class AService{
    private BService bService;
    public AService(BService bService) {
        this.bService = bService;
    }
    public void test(){
        System.out.println(bService);
    }
}

@Component
public class BService{
    private AService aService;
    public BService(AService aService) {
        this.aService = aService;
    }
}

因为你对AService进行实例化的时候,需要注入BService的Bean对象,但此时BService对象都没有创建Bean出来,那好了,需要去重新创建AService对象。这不又是循环依赖了嘛?

总结

三级缓存的作用是破解这个循环依赖问题。

用到的集合缓存有:

一级缓存作用(singletonObjects–ConcurrentHashMap):单例池;用来存放实现了完整生命周期的Bean对象,通过getBean()方法通过相同名字拿到同一个对象。

二级缓存作用(earlySingletonObjects–ConcurrentHashMap):用来保存 那些出现循环依赖的且需要提前暴露给其他的Bean对象用(比如在AService的Bean生命周期中填充BService属性时需要用到AService的代理对象) 的单例Bean对象的缓存。(有多个Bean依赖循环,就可以给每个Bean属性提供同一个代理对象)

三级缓存作用(singletonFactories–HashMap):用来存放Bean的普通对象,后面第二步需要要到Bean的普通对象来实现AOP。

性提供同一个代理对象)

三级缓存作用(singletonFactories–HashMap):用来存放Bean的普通对象,后面第二步需要要到Bean的普通对象来实现AOP。

creatingSet:用来给后面步骤2的时候判断该对象是否正在进行了循环依赖。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值