假设有两个类A和B
B是A的成员变量,A也是B的成员变量。
假设类A的bean为a,类B的bean为b。且IOC容器先处理A。
熟悉Spring容器初始化的同学,应该都知道,容器初始化的过程中,bean的创建是如下触发的:
getBean
的时候发现不存在,就去 createBean
。
bean的创建是在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
完成的。
doCreateBean
大致可以分为三步:
1、实例化bean:createBeanInstance
2、填充属性:populateBean
3、初始化bean:initializeBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// 实例化bean
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
......
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 放入3级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
......
try {
// 填充属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
......
return exposedObject;
}
其中第三步,只是Spring框架提供的 InitializingBean
接口的扩展,用于设置完properties之后做一些动作,对循环依赖没有影响。
循环依赖的处理只发生在第一步和第二步。
从以上代码可以看到,当A类的一个单例对象a被实例化之后,被立即放在了3级缓存内,具体的代码如下:
/**
* Add the given singleton factory for building the specified singleton
* if necessary.
* <p>To be called for eager registration of singletons, e.g. to be able to
* resolve circular references.
* @param beanName the name of the bean
* @param singletonFactory the factory for the singleton object
*/
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 放入3级缓存
this.singletonFactories.put(beanName, singletonFactory);
// 从2级缓存中移除(确保2级缓存没有)
this.earlySingletonObjects.remove(beanName);
// 标记这个bean已经创建过
this.registeredSingletons.add(beanName);
}
}
}
在给a设置属性B的时候,去对B进行 getBean
,发现不存在,也会对B进行 createBean
。
类B的对象b,在实例化之后,也会进行属性的设置,会对类A进行 getBean
,这部分就有了差异。
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// 这里去获取A的单例bean
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
getSingleton
的代码如下:
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 从1级缓存拿
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 从2级缓存拿
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 从3级缓存拿
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 放入2级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 从3级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
因为前面类A执行 doCreateBean
的时候,已经放进了3级缓存,所以b在设置属性的时候,是能拿得到a的。
这里的拿到的a还仅仅是执行了实例化的,并没有设置完属性。
b在执行完第二步设置属性,第三步初始化之后,又返回到a的第二步设置属性,第三步初始化。
至此,类A的对象a和类B的对象b,都已经创建成功。
最终总结流程图如下: