zoukankan      html  css  js  c++  java
  • Springboot Bean循环依赖问题

    参考博客原文地址:
    https://www.jb51.net/article/168398.htm
    https://www.cnblogs.com/mianteno/p/10692633.html
    http://www.pianshen.com/article/4112200143/


    1.构造器依赖循环

    代码示例:

    @Component
    public class A {
        private B b;
        @Autowired
        public A(B b) {
            this.b=b;
        }
    }
    
    @Component
    public class B {
        private C c;
        @Autowired
        public B(C c) {
            this.c = c;
        }
    }
    
    @Component
    public class C {
        private A a;
        @Autowired
        public C(A a) {
            this.a=a;
        }
    }
    

    启动运行后运行结果:

    可以看到异常的信息:

    //org.springframework.beans.factory.BeanCurrentlyInCreationException
    public BeanCurrentlyInCreationException(String beanName) {
    		super(beanName,
    				"Requested bean is currently in creation: Is there an unresolvable circular reference?");
    	}
    

    这种循环依赖没有什么解决办法,因为JVM虚拟机在对类进行实例化的时候,需先实例化构造器的参数,而由于循环引用这个参数无法提前实例化,故只能抛出错误。


    2.属性注入依赖循环

    代码示例:

    @Component
    public class A {
        @Autowired
        private B b;
        public A() {
            System.err.println(b);
        }
    }
    
    @Component
    public class B {
        @Autowired
        private C c;
        public B() {
            System.err.println(c);
        }
    }
    
    @Component
    public class C {
        @Autowired
        private A a;
        public C() {
            System.err.println(a);
        }
    }
    

    启动运行后运行结果:

    //程序正常启动,输出如下
    null
    null
    null
    
    

    结论:
    Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题


    3.源码分析 构造器循环依赖异常步骤及原因:

    创建一个Bean的过程是:实例化->初始化(属性)->放到缓存中,如下图

    这张图是核心

    getSingleton源码:

    //首次创建的beanName放入singletonsCurrentlyInCreation中
    protected void beforeSingletonCreation(String beanName) {
    		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    			throw new BeanCurrentlyInCreationException(beanName);
    		}
    	}
    

    构造器循环依赖,在初始化C时,需要先实例化A,但是A已经在singletonsCurrentlyInCreation有预实例化的记录了,所以此处抛出异常。

    public BeanCurrentlyInCreationException(String beanName) {
    		super(beanName,
    				"Requested bean is currently in creation: Is there an unresolvable circular reference?");
    	}
    

    源码分析 Spring如何解决属性注入 依赖循环问题:

    //相关类
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    org.springframework.beans.factory.support.AbstractBeanFactory
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
    

    可以看到,在实例化后,Bean被添加到singletonFactories中了,所以可以获取到Bean实例,解决了属性循环依赖问题

    try {
    					singletonObject = singletonFactory.getObject();
    					newSingleton = true;
    				}
    

    4.最终总结:

    构造器循环依赖:没有什么解决办法,因为JVM虚拟机在对类进行实例化的时候,需先实例化构造器的参数,而由于循环引用这个参数无法提前实例化,故只能抛出错误。
    属性循环依赖:Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题

    作者:往霄龙
    求其上者得其中,求其中者得其下
  • 相关阅读:
    JavaScript初探 三 (学习js数组)
    JavaScript初探 二 (了解数据)
    JavaScript初探 一(认识JavaScript)
    2019暑假学习督促安排
    【C#】让工具栏ToolStrip能触发焦点控件的Leave、Validating、DataError等事件以验证数据
    【C#】回调方法不通过object参数获得委托实例
    【SQL】找出行数与自增标识值不相等的表(即有缺行)
    【SQL】统计所有表的行数
    【SQL】靠谱的TRIM函数,附赠过程一枚
    【C#】在窗体中水平居中的控件,到了XP下不居中的解决办法
  • 原文地址:https://www.cnblogs.com/JQKA/p/11864777.html
Copyright © 2011-2022 走看看