One, foreword
The doCreateBean instantiation process is described in the previous blog, but the doCreateBean instantiation process is not described in detail. The doCreateBean instantiation process is described in the following blog. If you have not read the previous blog, you can learn about the bean loading process first. In my previous blog, I have covered this in detail. Spring source code parsing (5) bean instantiation process (1)_jokeMqc blog -CSDN blog
The following is a sketch of how Spring solves cycle dependencies. It’s important to understand how Spring solves cycle dependencies and what cycle dependencies Spring doesn’t solve.
What are cyclic dependencies
Circular dependencies are circular references, where two or more beans hold each other, such as A referring to B and B referring to A.
2.1 How does Spring solve loop dependencies
Spring container loop dependencies include constructor loop dependencies and setter loop dependencies. Spring dependencies fall into the following categories.
2.1.1 Constructor loop dependencies
Represents cyclic dependencies created by constructor injection. Subdependencies cannot be resolved except by throwing exceptions. Why is that? As you saw in the previous source code parsing, the Spring container places each singleton being created in a “bean being created” cache pool, which remains in place while the bean is being created.
<bean id="instanceA" class="com.tuling.circulardependencies.InstanceA" >
<constructor-arg name="instanceB" ref="instanceB"></constructor-arg>
</bean>
<bean id="instanceB" class="com.tuling.circulardependencies.InstanceB" >
<constructor-arg name="instanceA" ref="instanceA"></constructor-arg>
</bean>
Copy the code
Analysis of the above code is as follows:
- The Spring container creates an “InstanceA”bean by first going to the “cache pool of currently created beans” to see if the current bean is being created. If not, the bean is created. The current bean is then placed in the “cache pool of currently created beans” and its required construction parameter “InstanceB” is prepared.
- Spring creates “InstanceB”, first goes to the “currently created bean cache pool” to find whether the current bean is being created, if not, then creates the bean. The current bean is then placed in the “cache pool of currently created beans” and its required construction parameter “InstanceA” is prepared.
- The Spring container needs to create “InstanceA”, and it will see that the bean is being created, because it represents a loop dependency, and will throw an exception.
2.1.2 Sertter loop dependencies
Represents circular dependencies created by setter injection. Circular dependencies created by setter injection are preexposed by the Spring container for just-completed but uninitialized beans, and only singleton scoped beans can be resolved because Prototype is not preloaded into the cache.
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject(a) throws BeansException {
returngetEarlyBeanReference(beanName, mbd, bean); }}); }Copy the code
The specific steps are as follows:
- The Spring container creates a singleton “InstanceA”bean by first creating the bean from the lunch constructor, Determines whether the current bean is a singleton & whether loop dependencies are allowed & whether the bean is being created. If so, the early object (ObjectFactory) is exposed to the level 3 cache ahead of time. Property assignments are performed and setters inject “InstanceB”.
- The Spring container creates the singleton “InstanceB”, first creates the bean from the no-argument constructor, then exposes the bean to the tertiary cache ahead of time, and then the setter injects “IntanceA”.
- Inject “InstanceA” because the ObjectFactory factory is exposed ahead of time, and use it to return a bean that is being created ahead of time.
2.1.3 Prototype scope dependency handling
For “prototype” scoped beans, the Spring container cannot do dependency injection because the Spring container does not cache “prototype” scoped beans and therefore cannot pre-expose a bean being created.