- 实例化对象
- 对象填充属性
- BeanPostProcessor doBefore
- init-method
- BeanPostProcessor doAfter -- AOP是在这个阶段实现的
三级缓存Spring引入了第三级缓存来解决这个问题 , Map3 {k:name v:ObjectFactory} , 这个缓存的value就不是Bean对象了 , 而是一个接口对象由一段lamda表达式实现 。在这段lamda表达式中去完成一些BeanPostProcessor的执行 。
- 实例化A对象之后 , 将A的ObjectFactory对象放入Map3中 。
- 在填充A的属性阶段需要去填充B对象 , 而此时B对象还没有创建 , 所以这里为了完成A的填充就必须要先去创建B对象 。
- 创建B对象的过程中 , 实例化B的ObjectFactory对象之后 , 将B对象放入Map2中 。
- 执行到B对象填充属性阶段 , 又会需要去获取A对象 , 而此时Map1中没有A , 因为A还没有创建完成 , 但是我们继续从Map2中也拿不到 , 到Map3中获取了A的ObjectFactory对象 , 通过ObjectFactory对象获取A的早期对象 , 并将这个早期对象放入Map2中 , 同时删除Map3中的A , 将尚未创建完毕的A的引用赋值给a字段 。这样B对象其实就已经创建完整了 , 尽管B.a对象是一个还未创建完成的对象 。
- 此时将B放入Map并且从Map3中删除 。
- 这时候B创建完成 , A继续执行b的属性填充可以拿到B对象 , 这样A也完成了创建 。
- 此时将A对象放入Map并从Map2中删除 。
文章插图
取自别人家的图
源码步骤解析
- SpringBoot项目启动执行到SpringApplication#run 中的refreshContext(context); , 最终调用Spring容器的AbstractApplicationContext#refresh方法 , 开始初始化BeanFactory 。
- 在AbstractApplicationContext#refresh步骤中 , 执行到AbstractApplicationContext#finishBeanFactoryInitialization方法 , 开始完成 Bean 工厂初始化 。
- 执行到AbstracBeanFactory.preInstantiateSingletons() , 开始根据BeanFactory中的BeanDefinition信息初始化Bean对象 。
- 在AbstracBeanFactory.preInstantiateSingletons()方法中 , 发现A对象的BeanDefinition , 执行AbstracBeanFactory.getBean方法 , 获取A对象 。
- 在AbstracBeanFactory.getBean方法中 , 执行AbstracBeanFactory.doGetBean方法 , 获取A对象 。
- 在AbstracBeanFactory.doGetBean方法中执行DefaultSingletonBeanRegistry#getSingleton方法 , 尝试从缓存中获取A对象的单例对象缓存 。到一级缓存singletonObjects中找 , 未找到; 到二级缓存earlySingletonObjects中找 , 未找到; 到三级缓存singletonFactories中找 , 未找到;
- 再次执行DefaultSingletonBeanRegistry#getSingleton的重载方法 , 传入lamda表达式形式的ObjectFactory对象 , 内部调用AbstractAutowireCapableBeanFactory#createBean方法 , 尝试创建A对象 。
- 在AbstractAutowireCapableBeanFactory#createBean方法中 , 调用AbstractAutowireCapableBeanFactory#doCreateBean方法 , 实际执行创建A对象 。
- 实例化A对象 , 给字段赋值默认值后 , 调用DefaultSingletonBeanRegistry#addSingletonFactory方法 , 传入A对象的lamda表达式形式的ObjectFactory对象 , 将ObjectFactory对象放入三级缓存singletonFactories中 , 并从2级缓存earlySingletonObjects中移除(虽然这里没有) , 设置A对象已经开始注册 。此处传入的lamda表达式 , 内部调用了AbstractAutowireCapableBeanFactory#getEarlyBeanReference , 此方法用来执行实现了SmartInstantiationAwareBeanPostProcessor的后置处理器 , 比如实现AOP的AbstractAutoProxyCreator
- 然后开始执行A对象的AbstractAutowireCapableBeanFactory#populateBean , 进行属性填充 。
- 在进行属性填充时 , 发现依赖了B对象 , 执行AbstracBeanFactory.getBean方法 , 尝试获取B对象 。参考上面步骤4~9 。
推荐阅读
- 红茶对胃酸,云顶红茶图片
- 红茶蜂蜜养胃,蜂蜜红茶胃
- AMD|32核Zen 4加持!AMD新一代EPYC处理器现身:缓存翻番
- 红茶枸杞水,红茶能配枸杞和冰糖吗
- 别再自己瞎写工具类了,SpringBoot 内置工具类应有尽有,建议收藏
- 红茶二级三级区别,甘露和绿茶区别
- 春季喝红茶好吗,消化性溃疡喝黑茶好吗
- 发烧喝红茶,发烧了能喝红茶吗
- 红茶特级和特三级,滇江红茶多少钱
- 安溪三级红茶价格,滇江红茶多少钱