码迷,mamicode.com
首页 > 编程语言 > 详细

Spring三级缓存

时间:2021-04-22 16:18:40      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:业务开发   业务   head   www   对象   描述   构造器   有关   exception   

Spring解决循环依赖的问题
// 业务开发中经常这么写,field注入、setter注入都OK,但是构造器注入会报错BeanCurrentlyInCreationException
// 有这种循环依赖问题存在Spring却依然能够正常启动工作,为什么?Spring帮我们搞定了:三级缓存
@Service
public class AServiceImpl implements AService {
    @Autowired
    private BService bService;
}
@Service
public class BServiceImpl implements BService {
    @Autowired
    private AService aService;
}

在创建过程中,都是从三级缓存(对象工厂创建不完整对象),将提前暴露的对象放入到二级缓存,从二级缓存拿到后,完成初始化,放入一级缓存。

名称 描述
singletonObjects 一级缓存,存放完整的 Bean。
earlySingletonObjects 二级缓存,存放提前暴露的Bean,Bean 是不完整的,未完成属性注入和执行 init 方法。
singletonFactories 三级缓存,存放的是 Bean 工厂,主要是生产 Bean,存放到二级缓存中。

A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象”这种循环依赖的情景。

  1. 实例化 A,此时 A 还未完成属性填充和初始化方法(@PostConstruct)的执行,A 只是一个半成品。
  2. 为 A 创建一个 Bean 工厂,并放入到 singletonFactories 中。
  3. 发现 A 需要注入 B 对象,但是一级、二级、三级缓存均为发现对象 B。
  4. 实例化 B,此时 B 还未完成属性填充和初始化方法(@PostConstruct)的执行,B 只是一个半成品。
  5. 为 B 创建一个 Bean 工厂,并放入到 singletonFactories 中。
  6. 发现 B 需要注入 A 对象,此时在一级、二级未发现对象 A,但是在三级缓存中发现了对象 A,从三级缓存中得到对象 A,并将对象 A 放入二级缓存中,同时删除三级缓存中的对象 A。(注意,此时的 A 还是一个半成品,并没有完成属性填充和执行初始化方法)
  7. 将对象 A 注入到对象 B 中。
  8. 对象 B 完成属性填充,执行初始化方法,并放入到一级缓存中,同时删除二级缓存中的对象 B。(此时对象 B 已经是一个成品)
  9. 对象 A 得到对象 B,将对象 B 注入到对象 A 中。(对象 A 得到的是一个完整的对象 B)
  10. 对象 A 完成属性填充,执行初始化方法,并放入到一级缓存中,同时删除二级缓存中的对象 A。

一定需要三级缓存吗?

? 和AOP有关,第三级缓存的目的是为了延迟代理对象的创建(以应对循环依赖问题)。如果可以在实例化完成后立即创建代理对象,就不需要三级缓存了,所以二级缓存也是可以解决循环依赖的。为啥要额外多添加一层缓存?因为 Spring 的设计原则是在 Bean 初始化完成之后才为其创建代理

Spring三级缓存

标签:业务开发   业务   head   www   对象   描述   构造器   有关   exception   

原文地址:https://www.cnblogs.com/brightdagger/p/14687489.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!