场景 :A依赖B,同时B依赖A,那么Spring在创建Bean是如何防止出现循环加载导致内存溢出的
A ->B
B->A
首先在Spring-beans中的org.springframework.beans.factory.support.DefaultSingletonBeanRegistry 中有如下属性
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** Set of registered singletons, containing the bean names in registration order */
private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);
/** Names of beans that are currently in creation */
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
Spring在创建A实例时发现通过解析发现依赖B,那么A会通过getSingleton将ObjectFactory放入到earlySingletonObjects中,key是beanNane
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 != NULL_OBJECT ? singletonObject : null);
}
同时将beanName放在singlesCurrentlyInCreation中,由于A依赖B因此此处要先创建B对象,而B对象依赖A,所以B先从singletonsObjects、及缓存中getA对象,若果没有那么将从earlySingletonObjects获得A对应的ObjectFactory对象,接着完成B对象的创建,并将 B对象放在singletonFactories中及缓存中,此时B对象已有,那么开始创建A对象,创建完成后将earlySingletonObjects中对应的beanNane删除,同时将对象放在singletonFactories及缓存中。(这里A、B对象操作流程基本一致,都是先初始化依赖的Bean)
/**
* 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)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
重点说明:
A : A与B中的A是不是同一个对象?
Q : 一定是同一对象,因为他们最终都是指向同一个ObjectFactory对象地址