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,解决了循环依赖的问题

    作者:往霄龙
    求其上者得其中,求其中者得其下
  • 相关阅读:
    host 文件位置
    Django 前后端分离开发配置 跨域
    pycharm 关闭单词拼写检查(Typo: In word 'cacheable' )
    Python : argument name should be lowercase 警告处理解决方法
    pycharm 变量名 (Shadows built-in name 'id' )问题
    三体
    12.URL下载网络资源
    11.UDP多线程在线咨询
    10.UDP实现聊天
    9.UDP
  • 原文地址:https://www.cnblogs.com/JQKA/p/11864777.html
Copyright © 2011-2022 走看看