CASE where A field or setter of A depends on an instance of B and A field or setter of B depends on an instance of A Analysis: 1.A carries out the create process and finds itself dependent on B, and B does not use the create process at this time. DoCreateBean ()
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
The realization of a isSingletonCurrentlyInCreation (beanName) is:
protected void beforeSingletonCreation(String beanName) { if (! this.inCreationCheckExclusions.contains(beanName) && ! this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }}
So when is it going to be called? DefaultSingletonBeanRegistry.getSingleton(); AbstractBeanFactory. DoGetBean () also is AbstractBeanFactory. GetBean () call the above method. Here is another call link: AbstractApplicationContext. FinishBeanFactoryInitialization (the beanFactory) – >
beanFactory.preInstantiateSingletons()->AbstractBeanFactory.getBean().
Here, I’ll discuss the two main invocation links for now, and more on the rest later. We then analyze and execute addSingleOnFactory (beanName, () -> getEarlyBeanReference(beanName, MBD, bean)) if a circular reference is determined. Take a look at the implementation:
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);
}
}
}
Are you excited to see the familiar singletonFactories? At this point, A puts itself into the singleLonFactories. 2. If you find that you depend on object B, try to get(B), and find that B has not been created, so B goes through the create process. 3. When B initializes, it finds that it relies on A, tries to get(A) from SingleOnObjects, finds that there is no (A has not been initialized), and there is no earlySingleOnObjects (Level 2 cache). Finally, use A singleOnFactories, because A is already stored in A singleOnFactories in 1, so B can get A(although it is A semi-factory). 4. At this point, B can successfully complete the initialization and place itself in SingleTonObjects.
public Object getSingleton(String beanName, ObjectFactory<? > singletonFactory) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!) "); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } if (singleton) {// Add singleton (beanName, singletonObject) to singletonObjects; }}
Let’s see, the concrete implementation:
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); }}
5. At this point, return to A, A can get B, and finally A is initialized and entered into the first-level cache SingleOnObjects.