spring是如何解决循环依赖的

一、循环依赖场景

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;  
            }  
        }  
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kse_music

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值