Spring 源码深度解析(第 2 版)读书笔记(四)Bean的加载流程以及循环依赖的解决
进入方法内部,先看整个方法包含了哪些重要方法:
整个方法看完了,接着进入其中比较重要的方法看看:
第一个getSingleton方法,也就是尝试从缓存中拿
第二个方法:将拿到的bean看看是不是FactoryBean,如果是,那么返回的就是通过getObject方法返回的bean
会在判断是否单例之后,调用doGetObjectFromFactoryBean方法最后拿到bean
spring的惯例,都会在bean创建前后加入后置处理器,提高框架的扩展性
回到外层方法,看过FactoryBean的创建过程之后,接着看bean 的创建过程,第二个getSingleton方法:
先看看方法整体:
然后看看重要方法,SingletonFactory.getObject方法实际调用的createBean方法:
createBean方法中的resolveBeforeInstantiation方法
因为代理创建的对象就会直接返回了,所以初始化的后置方法在这里会被调用
方法回到外层,进入doCreateBean方法:
整个方法看完,就先进入第一个方法,也就是bean实例的创建方法:
构造方法分成两种,一种是有参构造,一种是无参构造,先看第一种:
有参构造的大部分时间花在匹配构造函数和参数上了,现在看看无参构造,相对简单很多:
在创建完bean之后,需要为其属性赋值,初始化等工作:
就算不使用@Autoware,其实到最后还是会在下面这个方法里面,给自动注入属性中
其实解析就是在拿到属性依赖的bean的名字然后去缓存拿或者创建bean
从这里开始,跟着走一圈看看循环依赖是怎么解决的,A-》B-》C-》A
在方法中,其实解决问题的关键是从一开始创建A就埋下伏笔,在创建A之前,会调用方法 1、beforeSingletonCreation(...)会将A的状态设置成SingletonCurrentlyInCreation是true,说明正在创建;然后在创建了A之后,马上调用2、addSingletonFactory(...)将A放进三级缓存中,也就是A只是个半成品;B、C都会经历这段过程,然后在C需要A的时候,那么在一开始的第一个getSingleton方法中,不再是返回null,而是在三级缓存中找到了半成品A,然后C就可以继续属性赋值然后初始化,返回一个完整的C,方法栈开始弹出,回到B的属性赋值上,这时候B拿到了完整的C,然后B也得以继续属性赋值和初始化,返回完整的B,重复上述步骤,回到A,拿到了完整的B,接着赋值和初始化,A创建完成,返回的是完整的A,至此,循环依赖解决了,不过也可以从这看出,如果DI是通过构造器的,或者bean是原型的,那么循环依赖将不能被解决,从而会报错。
一开始看源码会很懵逼,所以都是粗略看,不过在spring的使用上越来越熟练的时候,再看源码就会思路比较清晰,这次把bean的生命周期都和循环依赖看懂了部分,还是有所进步的,文中结合书中的一些看不懂的特殊的方法记录了一下,可能解释有误,请大家指出,谢谢。
==================================2021.1.11=====================================================
上文的@Autowire改成@Autowired才对
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?