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