当前位置: 首页 > news >正文

Spring之【循环引用】

目录

前置知识

        SingletonBeanRegistry

        DefaultSingletonBeanRegistry

Spring中处理循环引用的流程分析

        定义两个具有循环引用特点的Bean

        执行A的实例化

        执行A的属性填充(执行过程中发现A依赖B,就去执行B的实例化逻辑)

        执行B的实例化

        执行B的属性填充

        执行B的初始化

        执行A的属性填充(此时依赖的B已经完成了实例化和初始化放到容器的单例池中,接着执行之前没有执行完成的A的属性填充逻辑)

        执行A的初始化


前置知识

SingletonBeanRegistry

该接口中定义了一些和单例Bean有关的方法

package org.springframework.beans.factory.config;public interface SingletonBeanRegistry {/*** 往容器中添加单例bean对象*/void registerSingleton(String beanName, Object singletonObject);/*** 通过bean名字获取bean对象*/Object getSingleton(String beanName);/*** 判断容器中是否包含某bean名字的单例bean*/boolean containsSingleton(String beanName);/*** 获取容器中所有单例bean的名称集合*/String[] getSingletonNames();/*** 获取容器中单例bean对象的数量*/int getSingletonCount();
}

DefaultSingletonBeanRegistry

  • 定义了三个Map集合(也就是常说的三级缓存)
  • 定义了一个Set集合,用于存储正在创建的单例Bean的beanName
  • 对SingletonBeanRegistry接口提供方法的实现
package org.springframework.beans.factory.support;public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {// 一级缓存private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);// 三级缓存private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);// 二级缓存private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);// ...// 正在创建的单例Bean的beanNameprivate final Set<String> singletonsCurrentlyInCreation =Collections.newSetFromMap(new ConcurrentHashMap<>(16));/*** 对registerSingleton方法的实现*/@Overridepublic void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {// ...synchronized (this.singletonObjects) {// 通过beanName先从一级缓存中获取Object oldObject = this.singletonObjects.get(beanName);// 一级缓存中已经有该beanName的对象,就抛异常if (oldObject != null) {throw new IllegalStateException("Could not register object [" + singletonObject +"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");}// 一级缓存中没有该beanName的对象,就执行添加逻辑addSingleton(beanName, singletonObject);}}/*** 往容器中添加Bean*/protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {// beanName作为key,bean对象作为value,往一级缓存中添加this.singletonObjects.put(beanName, singletonObject);// 删除三级缓存中key为beanName的节点this.singletonFactories.remove(beanName);// 删除二级缓存中key为beanName的节点this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}// .../*** 对getSingleton方法的实现(通过beanName获取bean对象)*/    @Override@Nullablepublic Object getSingleton(String beanName) {// 调用重载方法return getSingleton(beanName, true);}/*** getSingleton第二个参数是boolean类型的重载方法*/@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {// 先从一级缓存中获取bean对象Object singletonObject = this.singletonObjects.get(beanName);// 一级缓存中没有该beanName对应的对象并且该beanName正在被创建if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {// 从二级缓存中获取singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {// 从三级缓存中获取ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// 执行三级缓存中的Lambda表达式的逻辑singletonObject = singletonFactory.getObject();// 放入二级缓存this.earlySingletonObjects.put(beanName, singletonObject);// 删除三级缓存中key为beanName的节点this.singletonFactories.remove(beanName);}}}}// 返回bean对象return singletonObject;}/*** getSingleton的重载方法* 第二个参数为Lambda表达式,为bean的创建过程*/public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {// ...synchronized (this.singletonObjects) {// 先从一级缓存中获取bean对象Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {// bean正在被创建,抛异常if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");}// ...// 创建bean之前,做一个标记,标记该beanName的bean正在创建中beforeSingletonCreation(beanName);boolean newSingleton = false;// ...try {// 执行Lambda的逻辑,执行bean的实例化和初始化流程singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {// ...}catch (BeanCreationException ex) {// ...}finally {// ...// 移除该beanName正在创建对象的标识afterSingletonCreation(beanName);}if (newSingleton) {// 将完成实例化和初始化的bean对象放入单例池中addSingleton(beanName, singletonObject);}}// 返回bean对象return singletonObject;}}
}

Spring中处理循环引用的流程分析

定义两个具有循环引用特点的Bean

package spring.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** A依赖B*/
@Component
public class A {@Autowiredprivate B b;
}
package spring.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** B依赖A*/
@Component
public class B {@Autowiredprivate A a;
}

执行A的实例化

一、DefaultListableBeanFactory#preInstantiateSingletons

遍历beanNames,根据beanName实例化非懒加载的单例Bean

二、AbstractBeanFactory#getBean

getBean - doGetBean

三、AbstractBeanFactory#doGetBean

先尝试从容器中获取,有就直接返回

四、DefaultSingletonBeanRegistry#getSingleton

此时单例池singletonObjects中并没有beanName为a的对象,且并没有正在创建中,所以返回null

五、AbstractBeanFactory#doGetBean

调用getSingleton方法并传入beanName+Lambda表达式

六、DefaultSingletonBeanRegistry#getSingleton

  1. 此时singletonObjects中没有a
  2. 标记a正在创建中
  3. 执行传入的Lambda表达式,即createBean方法

七、AbstractAutowireCapableBeanFactory#createBean

createBean - doCreateBean

八、AbstractAutowireCapableBeanFactory#doCreateBean

  1. Bean的实例化
  2. 可以看到,Bean对象已经创建(A@2126)
  3. 添加到singletonFactories中(key为beanName,value为ObjectFactory)

九、AbstractAutowireCapableBeanFactory#getEarlyBeanReference

并非将已经实例化但未初始化的Bean对象直接放入singletonFactories(三级缓存)中,考虑到代理对象,所以放入的是Lambda表达式,也就是该方法的执行逻辑

十、DefaultSingletonBeanRegistry#addSingletonFactory

放入singletonFactories(三级缓存)中,key为beanName,value为一个Lambda表达式

执行A的属性填充(执行过程中发现A依赖B,就去执行B的实例化逻辑)

一、AbstractAutowireCapableBeanFactory#doCreateBean

填充Bean

二、AbstractAutowireCapableBeanFactory#populateBean

  1. @Autowired注解是通过AutowiredAnnotationBeanPostProcessor解析的
  2. 这里执行AutowiredAnnotationBeanPostProcessor的postProcessProperties方法

三、AutowiredAnnotationBeanPostProcessor#postProcessProperties

找到A中的b字段需要注入

四、InjectionMetadata#inject

调用AutowiredAnnotationBeanPostProcessor中的inject方法

五、AutowiredAnnotationBeanPostProcessor#inject

调用DefaultListableBeanFactory的resolveDependency方法

六、DefaultListableBeanFactory#resolveDependency

resolveDependency - doResolveDependency

七、DefaultListableBeanFactory#doResolveDependency

  1. autowiredBeanName:依赖的beanName
  2. instanceCandidate:依赖的bean类型

八、DependencyDescriptor#resolveCandidate

调用DefaultListableBeanFactory的getBean方法,此时beanName为b,也就是接下来要执行B的实例化、属性填充、初始化逻辑

执行B的实例化

一、AbstractBeanFactory#getBean

getBean - doGetBean

二、AbstractBeanFactory#doGetBean

此时容器中没有b对象,返回null

三、AbstractAutowireCapableBeanFactory#createBean

createBean - doCreateBean

四、AbstractAutowireCapableBeanFactory#doCreateBean

  1. Bean的实例化
  2. 实例化后的Bean对象和Bean的类型
  3. 将b和对应的Lambda表达式添加到三级缓存中
  4. 此时三级缓存中存在a,b两个元素
  5. 填充b对象属性

 

执行B的属性填充

一、AbstractAutowireCapableBeanFactory#populateBean

同样的,通过AutowiredAnnotationBeanPostProcessor的postProcessProperties方法中处理@Autowired注解

二、AutowiredAnnotationBeanPostProcessor#postProcessProperties

找到B依赖A

三、InjectionMetadata#inject

执行AutowiredAnnotationBeanPostProcessor的inject方法进行属性注入

四、AutowiredAnnotationBeanPostProcessor#inject

调用DefaultListableBeanFactory的resolveDependency方法

五、DefaultListableBeanFactory#resolveDependency

resolveDependency - doResolveDependency

六、DefaultListableBeanFactory#doResolveDependency

获取到注入的beanName和类型,调用DependencyDescriptor的resolveCandidate方法

七、DependencyDescriptor#resolveCandidate

从容器中获取a对象

八、AbstractBeanFactory#getBean

getBean - doGetBean

九、DefaultSingletonBeanRegistry#getSingleton

此时发生了改变

  1. 从singletonObjects(一级缓存)中获取a,没有
  2. beanName为a的Bean正在创建
  3. 从earlySingletonObjects(一级缓存)中获取a,同样没有
  4. 但是,从三级缓存singletonFactories中获取a,能获取到,此时执行三级缓存中a对应的Lambda表达式的逻辑
  5. 执行Lambda表达式后拿到a对象
  6. 将a对象(实例化了但未进行初始化)放入二级缓存中
  7. 删除三级缓存中的a

 

十、AutowiredAnnotationBeanPostProcessor#inject

通过反射将a对象赋值给b对象的a字段

执行B的初始化

一、AbstractAutowireCapableBeanFactory#doCreateBean

调用initializeBean执行b对象后续的初始化逻辑

二、AbstractAutowireCapableBeanFactory#initializeBean

  1. Aware接口方法的回调(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)
  2. BeanPostProcessor的初始化前方法回调
  3. InitializingBean的afterPropertiesSet方法回调和自定义的初始化方法回调
  4. BeanPostProcessor的初始化后方法回调
  5. 返回完成初始化的b对象

三、DefaultSingletonBeanRegistry#getSingleton

  1. 此时已经执行完b对应的Lambda表达式的doCreateBean的逻辑,拿到的是b已经实例化并初始化好的Bean对象
  2. 删除b正在创建的标识
  3. 将b添加到一级缓存singletonObjects单例池中,删除三级缓存和二级缓存中的b
  4. 返回已经实例化并初始化好的b对象

执行A的属性填充(此时依赖的B已经完成了实例化和初始化放到容器的单例池中,接着执行之前没有执行完成的A的属性填充逻辑)

一、AutowireAnnotationBeanPostProcessor#inject

通过反射将b对象赋值给a对象的b字段(b对象中的a字段此时的值为完成了实例化但未进行初始化的a对象,没有进行初始化的对象并不影响别的对象去引用,后续对a对象进行初始化即可)

执行A的初始化

一、AbstractAutowireCapableBeanFactory#doCreateBean

执行a对象的初始化逻辑

二、DefaultSingletonBeanRegistry#getSingleton

执行完a对象的初始化逻辑,将a添加到一级缓存singletonObjects中,删除三级缓存和二级缓存中的a,至此完成了相互引用的a和b对象的实例化和初始化逻辑,并将它们放入了容器的单例池中

http://www.dtcms.com/a/309383.html

相关文章:

  • 第三阶段—8天Python从入门到精通【itheima】-140节(pysqark实战——基础准备)
  • 江协科技STM32 12-2 BKP备份寄存器RTC实时时钟
  • 二分查找(基础)
  • 启动中国蚁剑
  • 东芝时钟控制的双极步进电机驱动器TB67S209FTG
  • 关于皮带机流水线的控制思想解析
  • Sklearn 机器学习 文本数据 TF-IDF实现文本向量化
  • Linux 内存管理之 Rmap 反向映射
  • 每天一点跑步运动小知识
  • 使用gcc代替v语言的tcc编译器提高编译后二进制文件执行速度
  • 分布在背侧海马体CA1区域的位置细胞(place cells)对NLP中的深层语义分析的积极影响和启示
  • Ⅹ—6.计算机二级综合题23---26套
  • CIFAR10实战
  • gitlab+jenkins的ci/cd部署
  • 报错[Vue warn]: Failed to resolve directive: else如何解决?
  • PyTorch分布式训练:从入门到精通
  • 什么是CI/CD?
  • python学智能算法(三十))|SVM-KKT条件的数学理解
  • 测试平台如何重塑CI/CD流程中的质量协作新范式
  • LLM Prompt与开源模型资源(1)提示词工程介绍
  • 全新发布|知影-API风险监测系统V3.3,AI赋能定义数据接口安全新坐标
  • HTML无尽射击小游戏包含源码,纯HTML+CSS+JS
  • Redis 中 ZipList 的级联更新问题
  • Dockerfile详解 笔记250801
  • fingerprintjs/botd爬虫监听
  • Ajax笔记
  • SD-WAN在煤矿机械设备工厂智能化转型中的应用与网络架构优化
  • ansible.cfg 配置文件的常见配置项及其说明
  • AI量化模型解析黄金3300关口博弈:市场聚焦“非农数据”的GRU-RNN混合架构推演
  • 【立体标定】圆形标定板标定python实现