• Spring中循环依赖问题以及解决方案


    什么是循环依赖

    circular reference

    @Component
    public class A{
    	@Autowired
    	private B b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    @Component
    public class B{
    	@Autowired
    	private A a;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    循环依赖其实就是循环引用,创建A的过程需要B,创建B的过程需要A,这样就会产生循环依赖问题。

    创建一个Spring bean过程如下:
    1.通过构造方法对A进行实例化(创建了一个普通对象,是一个半成品)
    2.填充A的属性
    3.进行初始化
    4.AOP(创建一个代理对象)
    5.将代理对象放到单例池(此时bean是全成品)

    第二步可能会产生循环依赖。

    Spring如何解决单例的循环依赖

    通过三级缓存来解决

    DefaultSingletonBeanRegistry:

        @Nullable
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //1.Spring首先从一级缓存singletonObject中获取
            Object singletonObject = this.singletonObjects.get(beanName);
            //2.如果获得不到 并且显示对象正在创建
            if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
                Map var4 = this.singletonObjects;
                synchronized(this.singletonObjects) {
                //2.(1)就从二级缓存earlySingletonObjects中获取
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    //3.如果二级缓存中没有并且允许从singletonFactories中通过getObject拿到对象
                    //allowEarlyReference表示是否允许从singletonFactories中通过getObject拿到对象
                    if (singletonObject == null && allowEarlyReference) { 
                    //3.(1)从三级缓存中获取
                        ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                       //4.从三级缓存中获得到了对象之后
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            //4.(1)把这个对象加入二级缓存earlySingletonObjects中
                            this.earlySingletonObjects.put(beanName,singletonObject);
                            //4.(2)并且从三级缓存中移除
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
    // 		返回这个对象
            return singletonObject;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    哪些循环依赖Spring无法处理

    1.构造器的循环依赖无法解决:
    构造器的循环依赖是:A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象。
    因为加入三级缓存的前提是通过执行构造器生成了普通对象,所以如果是构造器的循环依赖无法解决。
    2.Spring不支持prototype类型的bean属性循环依赖:
    它会在创建spring容器context时报错,因为对于原型bean,spring容器只有在需要时才会实例化,初始化它.
    3.@Async增强的bean的循环依赖无法处理

  • 相关阅读:
    力扣刷题记录(Java)(四)
    [附源码]JAVA毕业设计高校智能排课系统(系统+LW)
    10.30刷题笔记
    基于YOLOv5的目标检测系统详解(附MATLAB GUI版代码)
    C语言学习推荐---小游戏
    可能是最漂亮的Spring事务管理详解
    DXF笔记:多义线线宽的绘制思路
    GNU screen -- Linux上快速部署管理jar包
    Python的基础语法——持续更新版
    2000万的行数在2023年仍然是 MySQL 表的有效软限制吗?
  • 原文地址:https://blog.csdn.net/qq_45968950/article/details/127673925