spring-ioc底层与三级缓存
获取一个 Bean 时,底层会层层调用 getBean 及类似方法。在 resolveNamedBean 中按类型找到候选 Bean,只有一个候选时,内部再次调用 getBean,最终返回包含 Bean 实例和名字的 NamedBeanHolder。getBean 内部进入 doGetBean,核心是调用 getSingleton 方法,这个方法存在重载,第一次调用会直接调用自身另一个重载版本,进入多层 if 嵌套的三级缓存查找逻辑:依次查一级单例对象池(成品区)、二级早期单例对象池(半成品区),都没有则加锁后重复上述两步,仍没有则去三级 singletonFactories 中调用 getObject() 造出对象,将其放入半成品区并删除工厂自身。关于循环依赖:A 和 B 互相依赖,若无此机制则死锁,现在的解法是 A 实例化后立刻将自己(已有内存地址)放入半成品区,去创建 B 时,B 需要 A 就重复上述缓存查找,在半成品区直接拿到 A,B 装配完成,A 随后也完成装配。三级缓存中存放的是实现了 ObjectFactory 接口的工厂。
在三级缓存,多层if嵌套中,用到了双检查锁,这个在懒汉式中也用到过,锁能保证并发情况下只有一个创建线程,双检查则保证不重复创建。
容器的启动有很多步骤,在昨晚初始化工作后,spring会调用refresh方法刷新容器,这也是spring容器启动的核心步骤,refresh()方法会执行一系列操作,12步。刷新前准备,获得一个新的bean工厂,准备bean工厂,预留给子类bean工厂的后序处理,执行bean工厂的后置处理器,注册bean后置处理器, 支持messageSource国际化消息,初始化应用事件多播器(事件驱动开发),留给子类继续做事的onrefresh,注册监听器,完成bean工厂的初始化(这一步完成了所有非懒加载的单例组件的创建,是应该关注的重点),最后完成容器刷新。

浙公网安备 33010602011771号