spring是如何解决循环依赖的

  • Post author:
  • Post category:其他




一、循环依赖场景

scope



二、解决手段

  • 三级缓存:
  1. singletonObjects: 一级缓存,用于保存实例化、注入、初始化完成的bean实例
  2. earlySingletonObjects: 二级缓存,用于保存实例化完成的bean实例
  3. singletonFactories: 三级缓存,用于保存bean创建工厂,以便于后面扩展有机会创建代理对象。

大致过程

  1. 在finishBeanFactoryInitialization中,开始初始化A,毋庸置疑通过反射
  2. 之后【非完美对象】开始设置属性字段,此时发现需要一个B的对象。同时已标记A处于正在初始化阶段
  3. 显然接下来,开始去初始化B的对象,同样的手法,到设置属性阶段,发现需要A对象
  4. 于是乎,spring又开始去初始化对象A的依赖,此时先从缓存singletonObjects去取,没有再去看是否正处于初始阶段,是则再从缓存earlySingletonObjects中取,再没有,则看是否存在allowEarlyReference,是则从singletonFactories中取
  5. 将早期对象A设置到B中,再把B设置到A中

  • 可以使用@Lazy注解等延迟实例化的机制(不推荐)

    蹩脚方式解决构造器级别的循环依赖



三、Refresh方法


     public void refresh() throws BeansException, IllegalStateException {  
        synchronized (this.startupShutdownMonitor) {  
            //清空.class文件缓存,设置启动刷新时间,同时至标志位active true,closed false,初始化servlet属性源,验证必须存在的属性,初始化一个早期的事件收集器  
            prepareRefresh();  
            //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从  
          //子类的refreshBeanFactory()方法启动  
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
            //为BeanFactory配置容器特性,例如类加载器、事件处理器等  
            prepareBeanFactory(beanFactory);  
            try {  
                //为容器的某些子类指定特殊的BeanPost事件处理器  
                postProcessBeanFactory(beanFactory);  
                //调用所有注册的BeanFactoryPostProcessor的Bean  
                invokeBeanFactoryPostProcessors(beanFactory);  
                //为BeanFactory注册BeanPost事件处理器.  
                //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件  
                registerBeanPostProcessors(beanFactory);  
                //初始化信息源,和国际化相关.  
                initMessageSource();  
                //初始化容器事件传播器.  
                initApplicationEventMulticaster();  
                //调用子类的某些特殊Bean初始化方法  
                onRefresh();  
                //为事件传播器注册事件监听器.  
                registerListeners();  
                //初始化所有剩余的单态Bean.  
                finishBeanFactoryInitialization(beanFactory);  
                //初始化容器的生命周期事件处理器,并发布容器的生命周期事件  
                finishRefresh();  
            }  
            catch (BeansException ex) {  
                //销毁以创建的单态Bean  
                destroyBeans();  
                //取消refresh操作,重置容器的同步标识.  
                cancelRefresh(ex);  
                throw ex;  
            }  
        }  
    }



版权声明:本文为dh798417147原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。