zoukankan      html  css  js  c++  java
  • 高频面试题:Spring 如何解决循环依赖?

    https://www.cnblogs.com/zzq6032010/p/11406405.html

     通过上面的步骤可以看出这三个map的优先级。其中singletonObjects里面存放的是初始化之后的单例对象;earlySingletonObjects中存放的是一个已完成实例化未完成初始化的早期单例对象;而singletonFactories中存放的是ObjectFactory对象,此对象的getObject方法返回值即刚完成实例化还未开始初始化的单例对象。所以先后顺序是,单例对象先存在于singletonFactories中,后存在于earlySingletonObjects中,最后初始化完成后放入singletonObjects中

            可以看到,在构造器执行的时候未完成属性的注入,而在调用方法的时候已经完成了注入。下面就一起看看Spring内部是在何时完成的属性注入,又是如何解决的循环依赖。

    至此,Spring循环依赖的总结分析结束,一句话来概括一下:Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题

     protected void addSingleton(String beanName, Object singletonObject) {
    2         synchronized (this.singletonObjects) {
    3             this.singletonObjects.put(beanName, singletonObject);//添加单例对象到map中
    4             this.singletonFactories.remove(beanName);//从早期暴露的工厂中移除,此map在解决循环依赖中发挥了关键的作用
    5             this.earlySingletonObjects.remove(beanName);//从早期暴露的对象map中移除
    6             this.registeredSingletons.add(beanName);//添加到已注册的单例名字集合中
    7         }
    8     }

     

    关于Spring bean的创建,其本质上还是一个对象的创建,既然是对象,读者朋友一定要明白一点就是,一个完整的对象包含两部分:当前对象实例化和对象属性的实例化。

    在Spring中,对象的实例化是通过反射实现的,而对象的属性则是在对象实例化之后通过一定的方式设置的。

    • Spring是通过递归的方式获取目标bean及其所依赖的bean的;
    • Spring实例化一个bean的时候,是分两步进行的,首先实例化目标bean,然后为其注入属性。

    结合这两点,也就是说,Spring在实例化一个bean的时候,是首先递归的实例化其所依赖的所有bean,直到某个bean没有依赖其他bean,此时就会将该实例返回,然后反递归的将获取到的bean设置为各个上层bean的属性的。

    简言之,两个池子:一个成品池子,一个半成品池子。能解决循环依赖的前提是:spring开启了allowCircularReferences,那么一个正在被创建的bean才会被放在半成品池子里。在注入bean,向容器获取bean的时候,优先向成品池子要,要不到,再去向半成品池子要。

    出现循环依赖一定是你的业务设计有问题。高层业务和底层业务的划分不够清晰,一般,业务的依赖方向一定是无环的,有环的业务,在后续的维护和拓展一定非常鸡肋

    构造注入无法解决循环依赖,而spring的三级缓存的存在是的,setter注入不存在循环依赖
     
    的确,工程问题和理论是两码事,工程内大家怎么方便怎么做,spring官方推构造器注入,在国外推广得也很不错,但是一到国内,受大量二流教程和培训班的影响,大家只会怎么方便怎么做,现在80%以上的人还是@Autowired字段的,还有为数不少的在用@Resource。
    小蚊子大人
  • 相关阅读:
    模拟4题解 T3奇袭
    模拟4题解 T1礼物
    [BZOJ2427][HAOI2010]软件安装
    [BZOJ4010][HNOI2015]菜肴制作
    deeplearning 重要调参参数分析
    论文阅读笔记八:SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation (IEEE2017)
    向github上提交自己的project
    c++ 链表基础功能实现
    c++实现 给定直角停车位两个点,求取剩余两点坐标。
    matlab转c++代码实现(主要包含C++ std::vector,std::pair学习,包含数组与常数相乘,数组相加减,将数组拉成一维向量,图片的读入等内容)
  • 原文地址:https://www.cnblogs.com/ywsheng/p/15001541.html
Copyright © 2011-2022 走看看