Spring源码系列:Spring Bean实例化流程(spring是如何解决循环依赖问题的)

spring实例化bean的过程是一个比较复杂的过程,简单的一个getBean方法 内部却做了很多的事情。当然getBean方法也是我们再研究spring源码道路上一个重要的方法。是不可能去绕开的,因为很多spring的扩展接口都是基于getBean方法去展开的。

笔者这次就不去一一 的把源码贴出来 逐行去分析了 因为这样我感觉效果不好。读着读着就不知道自己读到那个类的哪个类的哪个方法了,所以在这里 我以简略的流程图的方式来展示spring在实例化bean过程中的一些关键节点。读者可以自行下去翻阅源码看各个节点对应的具体源码。

 

Spring源码系列:Spring Bean实例化流程(spring是如何解决循环依赖问题的)_第1张图片

图中 绿色节点是执行spring扩展接口的节点。也就是执行spring提供的BeanPostProcessor和BeanFactoryPostProcessor的接口或其子接口的实现。spring在容器启动过程中和实例化bean过程中 大概前前后后有10几个这样的 扩展方法被执行。

看完上面的流程图 下面我们思考一个问题:spring是如何解决循环依赖问题的?

首先什么是循环依赖?  例如我有三个类A,B需要托管给SpringIOC容器 但是A 中注入了B  B中注入了A。形成一个环状依赖。

为了弄明白这个问题 我们把上图中的2 ,8 ,9 ,11四个节点的单独拿出来分析。

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

假如当前处于实例化A的阶段 。  代码执行到节点11处 发现 A依赖B , 所以去递归实例化B   但是在实例化B之前 有一步很关键的操作 就是就是节点9  节点9处已经将实例A的引用注册到singletonFactories。所以设置B的属性的时候会执行 getSingleton方法获取A的实例。singletonObject = singletonFactory.getObject();  这一行代码是实例化A的时候注册到singletonFactories的回调方法。下面我们看看节点9的源码:

//注册到singletonFactories
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));



protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

所以当执行 singletonFactory.getObject()就是在执行getEarlyBeanReference方法 该方法会返回一个早期的A实例的引用。

我们最后总结一下:实例一个Bean的时候 先从singletonObjects(单例缓存池) , earlySingletonObjects(早期单例缓存池),和singletonFactories(单例工厂缓存池) 中取找对应的Bean(节点2处)。如果找不到通过反射创建一个Bean 并找到当前Bean依赖的Bean注册到当前Bean的BeanDefinition中的externallyManagedConfigMembers属性中(节点8处 参考AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition),设置完依赖的Bean之后将当前节点注册到singletonFactories(节点9)。然后执行设置依赖Bean从singletonFactories获取(节点11处 设置属性处代码参考AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues).

这样就解决了循环依赖的问题。

 

 

 

 

你可能感兴趣的:(spring,spring循环依赖,spring,spring,boot,java)