springBean循环依赖

StringBean生命周期

1.spring启动,扫描所有的bean(注解的,xml配置的)放进spring容器中,在容器中将这写bean装换成BeanDefinition对象,放进一个map中
2.遍历这个BeanDefinitionMap
3.验证,是否懒加载,注入模型是原型还是单例 等等
4.验证后得到一个class
5.推断这个class的构造方法,一般都是默认构造方法,但是不绝对。
6.通过反射对这个class进行实例化
7. 提前暴露一个bean工厂对象
8. 填充属性 (Autowired 注解)
9. 执行各种aware接口,和生命周期回调方法
10.将bean放进单例池中

循环依赖出现的原因

	@Service
	public class A(){
		@Autowired
	    private B b;
	    }
	@Service
	public class B(){
		@Autowired
	    private A a;
	    }

有两个service,A 和 B,spring启动会去初始化这两个bean。当类A初始化bean的时候去填充属性,发现有个 B 类,此时A类的bean还没有生成,又要去初始化B类的bean,当到了属性填充时,发现又要去初始化A。这样就发现出现死循环了。
由于Spring bean 的生命周期很长,只有到了单例池中,才算完全初始化成功,所以会出现循环依赖。

springbean循环依赖的解决办法

springbean在初始化bean时,在实例化了对象之后,将这个对象存放进了map中。此时这个对象,还没有走完整个初始化生命周期,所以是个半对象,只是在内存空间分配了内存。

回到上面图片代码,当对A初始化的时候,实例化的对象,也就是半对象,会先放进一个map中,然后进行属性填充,此时在对B进行属性填充时,会先从单例池中取,如果没有,在从这个map中取。

为什么时三级缓存,而不是二级缓存

看上面的例子,好像两个两个缓存,一个存放半对象,一个存放完整的bean,就能完美解决循环依赖的问题。但是spring解决bean的循环依赖运用了三级缓存。
一级缓存ConcurrentHashMap<String, Object>:存放了经历了完整的初始化生命周期的bean,这是一个单例池。
二级缓存Map<String, Object>:存放了半对象,并且不用每次都去三级缓存,从工厂中取对象。
三级缓存Map<String, ObjectFactory<?>>:存放了最原始的对象,此时是个半对象,只有内存空间,没有属性填充;利于进行扩展,如增加 BeanPostProcessor ;

总结

三级缓存,是为了,不用每次都去从工厂处理数据。如果两次缓存,AOP的时候每次都产生新的代理对象,此时就需要一个缓存来存储这个代理对象。
只有单例才支持循环依赖,因为原型默认,在用的时候才回去实例化bean,而单例默认,在spring启动就实例化bean了。导致填充属性的时候会有问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值