Spring在启动过程中,使用到了三个map,称为三级缓存。
Spring启动过程大致如下:
- 创建beanFactory,加载配置文件
- 解析配置文件转化beanDefination,获取到bean的所有属性、依赖及初始化用到的各类处理器等
- 刷新beanFactory容器,初始化所有单例bean
- 注册所有的单例bean并返回可用的容器,一般为扩展的applicationContext
使用到三级缓存的地方就是上述的第三步,创建bean的时候
一级缓存singletonObjects
一级缓存存放的是已经初始化好的bean,即已经完成初始化好的注入对象的代理
二级缓存earlySingletonObjects
二级缓存存放的是还没有完全被初始化好的中间对象代理,即已经生成了bean但是这个bean还有部分成员对象还未被注入进来
三级缓存singletonFactory
三级缓存存放的是还未初始化完的bean,而这些bean只是早起的简单对象,并不是代理对象
缓存的执行顺序如下述代码:
但获取一个单例Bean的时候
会先查询二级缓存,如果发现二级缓存中有该对象,说明其这个bean已经被代理,有了代理对象,则就从二级缓存中获取,如果二级缓存中不存在该对象,则从三级缓存中查询,如果有该对象说明该对象已经被实力化,但是还未被代理,则通过三级缓存的getObject方法,获取该对象的代理bean并返回。
这样的执行好处是,获取对象的时候不用每次都通过getObject方法包装代理提高了执行性能。
综上所述
- 一级缓存是用于存放已经被初始化好的Bean,这些Bean已经是成品可以被使用。
- 二级缓存是用于存放半成品的Bean,存放在二级缓存中的是注入对象的代理,每次获取创建中的对象先从二级缓存中查询是因为这样就可以拿到代理对象,而不用每次都包装代理返回提高执行性能
- 三级缓存是用于存放原始的注入对象,这些对象还是简单对象并没有被代理,三级缓存是用于解决循环依赖问题,当对象A依赖对象B时,A对象就会被先临时存放在三级缓存中,然后初始化B对象。在这个时间点如果有别的注入对象需要依赖A对象就会从三级缓存中查询,并通过三级缓存的getObject方法生成代理对象然后将A对象从三级缓存中删除,放入二级缓存。