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

Spring循环依赖

时间:2020-04-23 00:19:49      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:string   直接   contain   cte   get   tar   object   creat   bean   

Spring是如何解决循环依赖的?

  • 三级缓存
//一级缓存,用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

//二级缓存 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

 //三级缓存 存放 bean 工厂对象,用于解决循环依赖
 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  • bean的创建会调用doCreateBean方法
  1. 先调用addSingletonFactory方法
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);
		}
	}
}
  1. 再调用getSingleton方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}
  1. 最后调用addSingleton方法
protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		this.singletonObjects.put(beanName, singletonObject);
		this.singletonFactories.remove(beanName);
		this.earlySingletonObjects.remove(beanName);
		this.registeredSingletons.add(beanName);
	}
}

总结

  • A先实例化(存入三级缓存),A初始化是发现依赖了B
  • B实例化(存入三级缓存),B初始化发现依赖了A,缓存中取得了A后删除三级缓存中的A并存入二级缓存,B初始化完成,B存入一级缓存.
  • 继续初始化A,由于B已经初始化完成,A也初始化完成,删除二级三级缓存.

Spring循环依赖

标签:string   直接   contain   cte   get   tar   object   creat   bean   

原文地址:https://www.cnblogs.com/qifengle1412/p/12757723.html

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