spring中的循环依赖
Posted 我爱看明朝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring中的循环依赖相关的知识,希望对你有一定的参考价值。
spring中的循环依赖
循环依赖的场景
1.构造器的循环依赖
2.field属性的循环依赖
如果两个对象是构造器的循环依赖,这中是没有什么办法解决,当A构造器依赖B,B构造器依赖A,无法提前实例化,以及缓存,因此无法处理。
spring对bean的创建是分三个步骤:1.通过构造器new出对象;2.设置属性;3.执行设置的初始化函数。field属性的循环依赖时,我们可以完成
构造器的执行,得到对象的引用地址,传给依赖的属性,后面再对这个对象设置相关的属性。就处理了field属性的循环依赖。
filed循环依赖示例
@service
public class ServiceA
@autowired
private ServiceB serviceb;
@service
public class ServiceB
@autowired
private ServiceA servicea;
@service
public class Demo
@Autowired
private ServiceA servicea;
@autowired
private ServiceB serviceb;
当spring创建Demo时,先执行默认无参构造器,创建对象Demo,然后设置属性servicea,serviceb,当创建serviceA时,先执行构造器,获得引用地址,加入缓存,填充A的属性再创建serviceB,
执行B的构造器,填充属性,从缓存中查到A的引用地址,填充,返回B的引用,给A; A,B完成创建。
spring在处理field的循环依赖使用了三级缓存方案。
源码分析
protected <T> T doGetBean()
// Eagerly check singleton cache for manually registered singletons.
// 从缓存中查询bean
Object sharedInstance = getSingleton(beanName);
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry
/** Cache of singleton objects: bean name --> bean instance */
// 一级缓存: 完整的bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** Cache of early singleton objects: bean name --> bean instance */
// 二级缓存: 只执行了构造器的bean
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** Cache of singleton factories: bean name --> ObjectFactory */
// 三级缓存:只执行了构造器的ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
protected Object getSingleton(String beanName, boolean allowEarlyReference)
// 一级缓存查询,是否存在
Object singletonObject = this.singletonObjects.get(beanName);
//如果不存在,并且bean正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
synchronized (this.singletonObjects)
// 从二级缓存查询
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存不存在以及允许从三级缓存中查询ObjectFactory
if (singletonObject == null && allowEarlyReference)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null)
//三级缓存查询到了ObjectFactory,通过ObjectFactory获取到引用地址
singletonObject = singletonFactory.getObject();
//从三级缓存获取到了,加入到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//在从三级缓存中移除
this.singletonFactories.remove(beanName);
return (singletonObject != NULL_OBJECT ? singletonObject : null);
//加入一级缓存存储ObjectFactory,此时只是执行了构造器,还未填充属性,获得了引用地址,
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects)
if (!this.singletonObjects.containsKey(beanName))
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
//一级缓存,完成bean的创建,加入到一级缓存
protected void addSingleton(String beanName, Object singletonObject)
synchronized (this.singletonObjects)
// 加入一级缓存,并且从二,三级缓存移除
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
总结
1.spring可以处理field属性的循环依赖,不能处理构造器的循环依赖
2.spring通过三级缓存解决了循环依赖问题
3.使用三级缓存解决循环依赖的基础是:spring对bean的创建分为三个步骤: 执行构造器、填充属性、执行初始化方法
参考
以上是关于spring中的循环依赖的主要内容,如果未能解决你的问题,请参考以下文章