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

Spring 创建bean的流程

Bean的创建流程

创建bean流程

Spring 三级缓存
循环依赖的解决流程:

因为成品和半成品对象无法放在都一个map,同时半成品不能暴露出来使用,因此Spring提出三级缓存来解决循环依赖问题

三级缓存定义如下:
/** 一级缓存 单例缓存池 用于保存我们所有的单实例bean */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 二级缓存 保存半成品bean实例,当对象需要被AOP切面代时,保存代理bean的实例beanProxy*/
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

/** 三级缓存 存放ObjectFactory,传入的是匿名内部类,ObjectFactory.getObject() 方法最终会
  调用getEarlyBeanReference()进行处理,返回创建bean实例化的lambda表达式。*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

这里三级缓存value类型ObjectFactory是一个函数式接口,可以传入一个lamda表达式:() -> {return this.getEarlyBeanReference(beanName, mbd, bean)}

循环依赖的源码流程:

入口:AbstarctApplicationContext.refresh()

getEarlyBeanReference方法根据当前bean是否需要代理获取bean对象还是aop代理对象

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
        Iterator var5 = this.getBeanPostProcessors().iterator();

        while(var5.hasNext()) {
            BeanPostProcessor bp = (BeanPostProcessor)var5.next();
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
    }
    return exposedObject;
}

思考:如果只有两个map能不能解决循环依赖?

三级缓存的作用是为了解决spring中Bean依赖注入时发生的循环依赖。如果不需要AOP,那么只需要二级缓存即可实现,如果有AOP,其实二级缓存也能够实现,但是会打破Bean的生命周期,不符合spring的原则,因为需要把AOP对象放入二级缓存中,那么就必须在所有需要AOP处理的Bean对象初始化之前就对Bean对象进行后置处理(生成AOP对象),即使没有发生循环依赖!这并不是spring想看到的,所以spring引入了三级缓存,而且存入的是<beanName, ObjectFactory>结构,ObjectFactory是一个lambda表达式,相当于一个回调函数,当发生循环依赖的时候,会进行lambda表达式的执行,获取到Bean对象或者 AOP代理对象,再将Bean对象或者 AOP代理对象存入二级缓存中,如果之后还有循环依赖指向该对象(类似 A 依赖 B , B 依赖 A和C , C 依赖 A这种情况),就直接从二级缓存里面获取,从而解决了循环依赖。(这里解释了为什么不直接在二级缓存里存放lambda表达式,因为同一个lambda表达式每执行一次,就会生成一个新的代理对象,不能保证单例)

附录


http://www.kler.cn/a/591850.html

相关文章:

  • java项目40分钟后token失效问题排查(40分钟后刷新页面白屏)
  • 20242817李臻《Linux⾼级编程实践》第四周
  • [spring]集成junit
  • 在 Vue 项目中引入静态图片有多种方式
  • 从Excel到搭贝的转变过程
  • VSTO(C#)Excel开发13:实现定时器
  • 【模拟面试】计算机考研复试集训(第八天)
  • 免费看付费电影网站制作,高清电影集合搜索引擎网站
  • 【Json-RPC框架】:Json::CharReader,parse函数反序列化的返回值
  • sparksql的Transformation与 Action操作
  • Redis 小记
  • LeetCode[42] 接雨水
  • HarmonyOS开发,A持有B,B引用A的场景会不会导致内存泄漏,代码示例告诉你答案
  • Ext系列文件系统
  • 全网首创/纯Qt/C++实现国标GB28181服务/实时视频/云台控制/预置位/录像回放和下载/事件订阅/语音对讲
  • 飞腾2000+/64核加固服务器
  • ruoyi-vue部署
  • 虚幻基础:组件组件通信
  • PreparedStatement:Java 数据库操作的安全与高效之道
  • STM32---FreeRTOS任务通知