spring如何解决循环依赖

12 篇文章 0 订阅

1. 构造器注入:无法解决

      构造器注入时,A,B都没有进行初始化对象(构造方法无法执行完成)

 

2.Spring 为了解决单例的循环依赖问题,使用了三级缓存。其中一级缓存为单例池(singletonObjects),二级缓存为提前曝光对象(earlySingletonObjects),三级缓存为提前曝光对象工厂(singletonFactories)。

 

        假设A,B循环依赖,A初始化时发现依赖B,这时就会去找B,B有发现属性初始化又依赖于A,这是又去找A,spring首先从singletonObjects(一级缓存)中尝试获取,如果获取不到并且对象在创建中,则尝试从earlySingletonObjects(二级缓存)中获取,如果还是获取不到并且允许从singletonFactories通过getObject获取,则通过singletonFactory.getObject()(三级缓存)获取。如果获取到了则移除对应的singletonFactory,将singletonObject放入到earlySingletonObjects,其实就是将三级缓存提升到二级缓存中. 找到A后,B完成初始化,接着完成A的初始化,在B对象中,存的只是A的引用,随着A初始化完成后整个流程完成。

 

 


3.为什么要使用三级缓存呢?二级缓存能解决循环依赖吗?

如果没有 AOP 代理,二级缓存可以解决问题。

有AOP的话,二级缓存会出问题:只通过二级缓存(earlySingletonObjects)获取的对象是一个原始的对象

以io流举例,我们一开始都是用的原始字节流,然后给别人用的也是字节流,但是,最后,我感觉不方便,我自己悄悄弄了个缓存字符流(类比代理对象),我是方便了,但是,别人用的,还是原始的字节流啊。

你bean不是单例吗?不能这么玩吧?

所以,这就是二级缓存,不能解决的问题。

 

4.三级缓存,怎么解决这个问题

要解决这个问题,必须在其他bean获取对象的时候,查找到最终形态的对象,即代理后的对象。

怎么做到这点呢?

加个三级缓存,里面不存具体的bean,里面存一个工厂对象。通过工厂对象,是可以拿到最终形态的代理后的对象。

里面的核心方法:

public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.add(cacheKey);
        // 1
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值