• spring 三级缓存 循环依赖


    源码笔记一

    5.1版本

    BeanDefinition

    定义了Bean 的基本信息。却分了加入IOC容器的方式

    16590646891849

    循环依赖

    容器说明
    singletonObjects一级缓存 单列池
    成品对象完成了属性赋值
    isSingletonCurrentlyInCreationlist 记录正在创建的对象 beanName
    earlySingletonObjects二级缓存 存放这早期对象
    bean调用了 构造方法,还没给bean属性赋值
    singletonFactories三级缓存 存放bean信息和lambda
    在IOC后期过程中,Bean调用构造方法时,吧早期对象包裹成ObjectFactory
    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
      #getSingleton(java.lang.String, boolean)
      
      /*
      beanName : bean 的名称
      allowEarlyRerence 是否允许暴露早期对象,通过参数可以控制是否能够解决以来循环
      return: null - IOC容器加载单列bean的时候,第一次进来返回null
      				单列对象 - IOC加载了单列是咧,第二次进来获取到当前bean
      				早期对象 - 用于解决以来循环的问题
      */
      protected Object getSingleton(String beanName, boolean allowEarlyReference)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    @Nullable
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
          // 通过beanName 从单列池中获取 
            Object singletonObject = this.singletonObjects.get(beanName);
          // singletonsCurrentlyInCreation 里面存放这正在创建中的对象
            if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
                synchronized(this.singletonObjects) {
                  /*
                  earlySingletonObjects 二级缓存存放早期的对象
                  */
                    singletonObject = this.earlySingletonObjects.get(beanName);
                  // 是否允许暴露的早期对象
                    if (singletonObject == null && allowEarlyReference) {
                     // 从三级 缓存中获取  当bean调用构造方法的时候,把早期对象包裹成一个ObjectFactory 放入三级缓存
                        ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                          //这里 getObject 拿到是一个 对象,不是bean
                            singletonObject = singletonFactory.getObject();
                          //吧这个对象放入 二级缓存
                            this.earlySingletonObjects.put(beanName, singletonObject);
                          // 吧对象从三级缓存删除
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
    
            return singletonObject;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    三级缓存放入点

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
      #doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
     
    // 第四次调用后置处理器 判断是否需要Aop【Aop提前】
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    
    • 1
    • 2
    • 3
    • 4
    • 5

    普通bean 的获取不会尝试三级缓存

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
      #doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      // fasle 不会走三级缓存,在aop 的时候会走三级缓存
    Object earlySingletonReference = getSingleton(beanName, false);
    
    • 1
    • 2
    • 3
    • 4

    AbstractAutowireCapableBeanFactory

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
      #doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    
    • 1
    • 2

    这里调用了多次后置处理器

    doCreateBean.png

    底部

  • 相关阅读:
    读《凤凰架构》- 从HTTP/1.0到QUIC
    [SpringBoot]SpringBoot概述(简介、官网构建、快速启动)
    springboot+ssm基于vue.js的客户关系Crm管理系统
    最优化方法Python计算:信赖域算法
    内核概述及配置编译
    Linux:进程的状态理解
    明修"栈"道——越过Android启动栈陷阱
    在SpringBoot框架下,接口有读个实现类,在不改变任何源码的情况下,SpringBoot怎么知道给接口注入哪个实现类的依赖呢?
    【微信小程序】slider滑动选择器(82/100)
    常用应届生Java开发笔试面试题(更新中)
  • 原文地址:https://blog.csdn.net/MXqihang/article/details/126118156