How Spring resolves circular dependency between beans
- Object’s instantiation is done via reflection
ApplicataionContext.getBean()
, and after that object’s properties are done via object’s init - When object A needs another object B, we will recursively uses
ApplicataionContext.getBean()
to get A, and then inject into B. At this time, the objects are created, but their properties are not set. - Suppose A has B, and B has A as member, on init
- A insantiated first
- A finds that B is needed,
getBean()
on B- B is instantiated
- B finds that A is needed,
getBean()
on A. At this time, A’s reference is registered already, so Spring returns reference to A in the first step - B sets the member reference to A, finishes the init, and return
- A now gets the reference to B, set its member reference to B, and returns
Implementation
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//first time ever to create
synchronized (this.singletonObjects) {
//singletonObjects is { bean_name : ObjectFactory} map
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//bean is marked in creation, but not created, do it now
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName); //make sure we init only once
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}