源码讲解Spring的循环依赖

什么是循环引用,就不用我多逼逼了,直接上代码,全程debug分析源码

@Configuration
@ComponentScan({"com.carry"})
public class Appconfig {
}
@Component
public class X {
 
	@Autowired
	private Y y;
 
	public X() {
		System.out.println("x的构造方法");
	}
}
 
@Component
public class Y {
	
	@Autowired
	private X x;
 
	public Y() {
		System.out.println("y的构造方法");
	}
}

我们先记住这两个概念——spring bean(以下简称bean)和对象;
1、spring bean——受spring容器管理的对象,可能经过了完整的spring bean生命周期(为什么是可能?难道还有bean是没有经过bean生命周期的?答案是有的,具体我们后面文章分析),最终存在spring容器当中;一个bean一定是个对象
2、对象——任何符合java语法规则实例化出来的对象,但是一个对象并不一定是spring bean

好了,进入正题,我们从doGetBean开始,看下doGetBean方法
 

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
 
		String beanName = transformedBeanName(name);
		Object bean;
 
		// Eagerly check singleton cache for manually registered singletons.
		//先从缓存中获取单例bean,对于单例bean,整个IOC容器只创建一次
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			// 获取给定bean的实例对象,主要是完成factorybean的相关处理
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
 
		else {
			//缓存中没有单例bean
			//如果我们已经创建此bean实例,
			//但是由于循环引用的问题导致实例化对象失败
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
 
			// Check if bean definition exists in this factory.
			//对ioc容器中是否存在指定名称的BeanDefinition进行检查,首先检查
			// 能在当前的BeanFactory中获取所需的Bean,如果不能委托当前容器的父类
			// 去查找,如果还找不到则沿着容器的继承体系向父容器查找 (正常来说,这个parentBeanFactory肯定是null)
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					//委派父容器根据根据指定名称和显式的参数查找
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					//委派父容器根据根据指定名称和类型查找
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
 
			// 创建的Bean是否需要进行类型验证,一般不需要
			if (!typeCheckOnly) {
				// 像容器标记指定的Bean已经被创建
				markBeanAsCreated(beanName);
			}
 
			try {
				// 主要解决Bean继承时子类合并父类公共属性问题
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
 
				// Guarantee initialization of beans that the current bean depends on.
				// 获取当前Bean依赖的所有Bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						//递归调用getBean方法,获取当前bean的依赖Bean
						registerDependentBean(dep, beanName);
						try {
							//把被依赖 Bean 注册给当前依赖的 Bean
							getBean(dep);
						}
						
					}
				}
 
				// Create bean instance.
				if (mbd.isSingleton()) {
					// 这里使用了一个匿名内部类,创建bean实例对象,并且注册给所依赖的对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 创建一个指定bean的实例对象,如果有父级继承,则合并子类和父类的定义
							return createBean(beanName, mbd, args);
						}
				
					});
					// 获取给定Bean的实例对象
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
 
				// 如果是原型模式的bean对象
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						// 回调 beforePrototypeCreation 方法,默认的功能是注册当前创建的原型对象
						beforePrototypeCreation(beanName);
						// 创建bean
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						//回调 afterPrototypeCreation 方法,默认的功能告诉 IOC 容器指定 Bean 的原型对象不再创建
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
 
				//要创建的 Bean 既不是单例模式,也不是原型模式,则根据 Bean 定义资源中
				//配置的生命周期范围,选择实例化 Bean 的合适方法,这种在 Web 应用程序中
				//比较常用,如:request、session、application 等生命周期
				else {
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
				
				}
			}
			
		}
 
		// Check if required type matches the type of the actual bean instance.
		// 对创建的bean实例对象,进行类型检查
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
		}
		return (T) bean;
	}

这个doGetBean太长了,我们来精简一下:

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
 
		String beanName = transformedBeanName(name);
		// 定义一个对象,用来存将返回的Bean
		Object bean;
 
		// Eagerly check singleton cache for manually registered singletons.
		//先从缓存中获取单例bean,对于单例bean,整个IOC容器只创建一次
		//doGetBean1
		Object sharedInstance = getSingleton(beanName);
		//doGetBean2
		if (sharedInstance != null && args == null) {
			// 获取给定bean的实例对象,主要是完成factorybean的相关处理
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
			//缓存中没有单例bean
			//如果我们已经创建此bean实例,
			//但是由于循环引用的问题导致实例化对象失败
			//doGetBean3
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
				// Create bean instance.
				//doGetBean4
			if (mbd.isSingleton()) {
				// 这里使用了一个匿名内部类,创建bean实例对象,并且注册给所依赖的对象
				sharedInstance = getSingleton(beanName, () -> {
					try {
						// 创建一个指定bean的实例对象,如果有父级继承,则合并子类和父类的定义
						return createBean(beanName, mbd, args);
					}
				});
			}
		}
		return (T) bean;
	}

下面将会对这个做了标记的doGetBean去做分析

doGetBean1:getSingleton

spring在创建一个bean之前先检查一下beanName是否被手动注册过到单例池当中,我们这是第一次

初始化,肯定为null

总结一下 Object sharedInstance = getSingleton(beanName);目前看来主要是用于在spring初始化bean的时候判断bean是否在容器当中;以及供程序员直接get某个bean。

注意笔者这里用了 目前这个词;因为getSingleton(beanName);这个方法代码比较多;他里面的逻辑是实现循环依赖最主要的代码,文章下面我会回过头再来讲这个方法的全部意义;

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;
	}

下面接着分析doGetBean2

//doGetBean2
		if (sharedInstance != null && args == null) {
			// 获取给定bean的实例对象,主要是完成factorybean的相关处理
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

由于 sharedInstance = =null 故而不会进入这个if分支,那么什么时候不等于null呢?

1在spring初始化完成后程序员调用getBean(“x”)的时候得到的sharedInstance 就不等于null;

2循环依赖的时候第二次获取对象的时候这里也不等于空;比如X 依赖 Y;Y依赖X;spring做初始化第一次执行到这里的时候X 肯定等于null,然后接着往下执行,当执行到属性注入Y的时候,Y也会执行到这里,那么Y也是null,因为Y也没初始化,Y也会接着往下执行,当Y执行到属性注入的时候获取容器中获取X,也就是第二次执行获取X;这个时候X则不为空;至于具体原因,读者接着往下看

至于这个方法到底做了什么就不分析了,把源码贴出来大家看下就行

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		//如果bean不是工厂,不要让调用代码尝试取消对工厂的引用。
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
		}
		//现在我们有了bean实例,它可以是普通bean或FactoryBean。
		//如果它是一个FactoryBean,我们就用它来创建一个bean实例,除非
		//打电话的人实际上想要一个工厂的参考号
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
 
		Object object = null;
		if (mbd == null) {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

我们接着分析doGetBean3

spring再创建bean的时候,不管是单例还是原型都会add到这个集合里面,创建完成以后就会remove掉

接着分析doGetBean4

if (mbd.isSingleton()) {
					// 这里使用了一个匿名内部类,创建bean实例对象,并且注册给所依赖的对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 创建一个指定bean的实例对象,如果有父级继承,则合并子类和父类的定义
							return createBean(beanName, mbd, args);
						}
					});
					// 获取给定Bean的实例对象
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

这里又调用了一次getSingleton,如果有印象上面也调用了一次getSingleton,这是方法重载,两个getSingleton方法并不是同一个方法,读者自己看参数就行,为了区别我这这里叫做第二次调用getSingleton;上文的叫做第一次调用getSingleton;

当然第二次getSingleton就会把我们bean创建出来,换言之整个bean如何被初始化的都是在这个方法里面。

接下来就要研究第二次getSingleton方法的内容了,因为我说了整个bean初始化过程都在里面体现了;

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 调用createBean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

同样,把这代码删减一下:

public Object getSingleton(String beanName, ObjectFactory<?> 
singletonFactory) {
	//getSingleton2 -1
	Object singletonObject = this.singletonObjects.get(beanName);
			//getSingleton2 -2
			if (singletonObject == null) {
				//getSingleton2 -3
				if (this.singletonsCurrentlyInDestruction) {
					throw new Exception(beanName,
							"excepition");
				}
				//getSingleton2 -4
				beforeSingletonCreation(beanName);
				//getSingleton2 -5
				singletonObject = singletonFactory.getObject();	
			}
			return singletonObject;
		}
		

//getSingleton2 -2 开始解析

if (singletonObject == null) {
上面解释了,在spring 初始化bean的时候这里肯定为空,故而成立

//getSingleton2 -3 开始解析

if (this.singletonsCurrentlyInDestruction) {
			throw new Exception(beanName,
					"excepition");
		}

这行代码其实比较简单,判断当前实例化的bean是否正在销毁的集合里面;spring不管销毁还是创建一个bean的过程都比较繁琐,都会先把他们放到一个集合当中标识正在创建或者销毁;所以如果你理解了前面那个正在创建集合那么这个正在销毁集合也就理解了;但是不理解也没关系,下面会分析这些集合;

如果一个bean正在创建,但是有正在销毁那么则会出异常;为什么会有这种情况?其实也很简单,多线程可能会吧;

//getSingleton2 -4 假设解析

beforeSingletonCreation(beanName);

这段代码就比较重要了,关于上面说那个正在创建和正在销毁的集合;这段代码就能解释,所以如果上面你没看明白那个集合的意义,这里用spring源码来说明一下;先看看当代码执行到这里的时候语境

当spring觉得可以着手来创建bean的时候首先便是调用beforeSingletonCreation(beanName);判断当前正在实例化的bean是否存在正在创建的集合当中,说白了就是判断当前是否正在被创建;因为spring不管创建原型bean还是单例bean,当他需要正式创建bean的时候他会记录一下这个bean正在创建(add到一个set集合当中);故而当他正式创建之前他要去看看这个bean有没有正在被创建(是否存在集合当中); 为什么spring要去判断是否存在这个集合呢?原因很多除了你们能想到了(你们能想到的基本不会出现,比如并发啊,重复创建什么的,因为他已经做了严格并发处理),其实这个集合主要是为了循环依赖服务的,怎么服务的呢?慢慢看吧,首先我们来看下这行 代码的具体内容

protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) &&
				// 把beanName加到这个map里面
				!this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

//getSingleton2 -5 开始分析

singletonObject = singletonFactory.getObject();
可能有读者已经忘记了singletonFactory这个对象怎么来的了;再把代码贴一遍吧

ObjectFactory<?>  singletonFactory = new ObjectFactory(){
	public Object getObject(){
		//其实这是个抽象类,不能实例化
		//createBean是子类实现的,这里就不关心了
		//你就理解这不是一个抽象类吧
		AbstractBeanFactory abf = new AbstractBeanFactory();
		Object bean = abf.createBean(beanName, mbd, args);
		return bean;
	};
};
//传入 beanName 和singletonFactory 对象
sharedInstance = getSingleton(beanName,singletonFactory);
 

singletonFactory.getObject();调用的就是上面代码中getObject方法,换言之调用的是abf.createBean(beanName, mbd, args);把创建好的bean返回出来;至此第二次getSingleton方法结束,bean通过singletonFactory.getObject();调用createBean建完成;接下来分析createBean的源码,继续探讨循环依赖的原理;
AbstractAutowireCapableBeanFactory#createBean()方法中调用了doCreateBean方法创建bean
 

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
 
		// Instantiate the bean.
		//BeanWrapper是用来持有创建出来的bean对象的
		BeanWrapper instanceWrapper = null;
		// 如果是singleton先把缓存中同名的bean清除
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
 
		// Allow post-processors to modify the merged bean definition.
		//调用Postprocess后置处理器
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}
 
		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 向容器中缓存单例模式的Bean对象,以防循环引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
 
		// Initialize the bean instance.
		//bean对象的初始化,依赖注入在此触发
		//这个 exposedObject 在初始化完成之后返回作为依赖注入完成后的 Bean
		Object exposedObject = bean;
		try {
			// 将Bean实例对象封装,并且bean定义中配置的属性赋值给实例对象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化bean对象
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
 
		if (earlySingletonExposure) {
			// 获取指定名称的已经注册的单例模式Bean对象
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				//根据名称获取的已注册的 Bean 和正在实例化的 Bean 是同一个
				if (exposedObject == bean) {
					//当前实例化的bean初始化完成
					exposedObject = earlySingletonReference;
				}
				//当前bean依赖其他bean,并且当发生循环引用时不允许新创建实例对象
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}
 
		// Register bean as disposable.
		//注册完成依赖注入的bean
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}
 
		return exposedObject;
	}

instanceWrapper = createBeanInstance(beanName, mbd, args);

createBeanInstance 顾名思义就是创建一个实例,注意这里仅仅是创建一个实例对象,还不能称为bean,只是X对象创建,属性还没填充呢

这个如何创建出来的,可以看我Spring Bean的实例化过程

接着分析

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));

这个肯定是ture,会调用addSingletonFactory

addSingletonFactory(beanName,singletonFactory);顾名思义添加一个单例工厂;其实这里要非常注意,因为大部分资料里面在说到spring循环依赖的时候都说是提前暴露一个半成品bean;笔者觉得这个不严格;甚至算错误了,所谓的提前暴露就是这里的add,但是我们看到源码并不是add一个bean的,而是add一个工厂对象——singletonFactory;两种说法有什么区别呢?区别可大了,简直天壤之别;我们慢慢分析;这里bean和工厂有什么区别呢?在当前的语境下面bean就是x对象经历完spring生命周期之后;所谓的半成品bean,可能还没有经历完整的生命周期;而工厂对象呢?如果你去ObjectFactory的源码或者直接顾名思义他是一个能够产生对象的工厂,或者叫能够产生bean的工厂;换句话说bean是一个产品,而工厂是产生这些产品的公司;如果还不能理解换成天上人间可能好理解——冰火和全套的区别,冰火是全套里面的一个项目,除了冰火还有其他项目;

那么spring在这里add的是singletonFactory这个工厂对象(这个工厂可以产生半成品对象),而不是一个半成品对象;相当于这里add的是全套,而不是冰火;将来拿出来的时候是得到工厂,继而通过工厂得到半成品bean;将来拿出来的是全套,你可以在全套里面肆意选择一个项目;不知道我又没有解释清楚这个问题;

当然说了这么多可能你还是没明白为什么需要在这里add这个工厂对象呢?还有add到哪里去呢?

我们首先分析bean工厂对象到底add到哪里去了,查看源码

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,比如spring各种内置bean,比如你项目里面其他的已经创建好的bean,但是在X的创建过程中,一级缓存中绝对是没有xbean的,也没用y;因为spring创建bean默认的顺序是根据字母顺序的;

二级缓存:里面现在仅仅存在一个工厂对象,对应的key为x的beanName,并且这个bean工厂对象的getObect方法能返回现在的这个时候的x(半成品的xbean)
put完成之后,代码接着往下执行;

三级缓存:姑且认为里面什么都没有吧

populateBean(beanName, mbd, instanceWrapper);
populateBean这个方法可谓大名鼎鼎,主要就是完成属性注入,也就是大家常常说的自动注入;假设本文环境中的代码运行完这行代码那么则会注入y,而y又引用了x,所以注入进来的y对象,也完成了x的注入;什么意思呢?首先看一下没有执行populateBean之前的情况

没有执行populateBean之前只实例化了X,Y并没实例化,那么Y也不能注入了;接下来看看执行完这行代码之后的情况

x 填充 y (简称 xpy)首先肯定需要获取y,调用getBean(y),getBean的本质上文已经分析过货进入到第一次调用getSingleton,读者可以回顾一下上文我对doGetBean方法名字的解释里说了这个方法是创建bean和获取共用的;

第一次getSingleton会从单例池获取一下y,如果y没有存在单例池则开始创建y

创建y的流程和创建x一模一样,都会走bean的生命周期;比如把y添加到正在创建的bean的集合当中,推断构造方法,实例化y,提前暴露工厂对象(二级缓存里面现在有两个工厂了,分别是x和y)等等。。。。重复x的步骤;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring循环依赖是指两个或多个Bean之间相互依赖,形成一个循环引用的关系。在Spring容器启动的过程中,如果存在循环依赖,那么默认情况下会抛出BeanCurrentlyInCreationException异常。 下面是Spring循环依赖源码分析: 1. 当我们向Spring容器中注入一个Bean时,Spring会先检查这个Bean是否已经正在创建中(正在创建的Bean是无法注入的),如果正在创建中,则直接返回一个早期引用,否则继续创建Bean。 2. 在Bean的创建过程中,当遇到依赖注入(如@Autowired注解)时,Spring会检查要注入的Bean是否已经在创建中。如果是,则返回一个代理对象作为占位符,等待真正的Bean创建完毕后再进行注入。 3. Spring使用三级缓存来解决循环依赖问题。第一级缓存是单例池,存放已经创建好的单例Bean。第二级缓存是提前暴露的ObjectFactory,存放早期引用。第三级缓存是用于存放正在创建中的Bean的缓存,用于检测循环依赖。 4. 当检测到循环依赖时,Spring会尝试使用构造函数的方式完成循环依赖。它会先创建一个空对象,并将其放入到第三级缓存中。然后调用构造函数去创建这个Bean,此时依赖的Bean会返回一个早期引用。最后,将这个Bean加入到第一级缓存中,并开始注入依赖。 5. 当所有的Bean都创建完成后,Spring会触发后置处理器的回调方法,完成Bean的初始化。 总结:Spring循环依赖通过使用三级缓存和构造函数来解决,在Bean创建过程中动态地判断和处理循环依赖关系,确保所有的Bean都能被正确地创建和注入。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值