How Spring handles circular dependencies
The key to the solution is to expose the unfinished beans in advance.
Creating a Bean in Spring is divided into three steps
- Instantiation, createBeanInstance, that is, new a bean object.
- Attribute fill, populateBean, that is, set the attribute value into the bean object.
- InitializeBean.
Solutions to cyclic dependencies
- First create the bean instance of A. At this time, A is incomplete because there is no attribute filling (that is, B dependency is not injected), and at this time, use a map to save the incomplete A.
- To create B, B requires injection of A, so you can get incomplete A from the map. At this time, B is complete, and then A can inject B.
In Spring, the problem of circular dependency can only be solved by satisfying the following two points at the same time.
1. The dependency beans must be singletons.
- Because if it is a prototype pattern, you need to create a new object. When creating A1, you need to create A1's dependency B1
- Then when creating B1, you need to create B1's dependency A2, so you need to create B2, A3, B3... to enter the process of infinite creation of objects.
2. The dependency injection method cannot be all constructor injection.
- If it is all constructor injection, that is, A(B b), it means that when creating an instance of A's Bean, B needs to be obtained. Then, you need to create a bean instance of B, but B also needs to inject A, that is, B(A a) into the constructor. At this time, B needs to find the incomplete A in the map, but it cannot be found because A's Bean entity has not been created yet (still waiting for B).
- Note: Spring containers create beans in alphabetical order, so in loop dependencies, beans with letters that are in front of them cannot use constructor injection.
Spring solves the entire process of circular dependency
First, learn about the three maps related to Spring beans
-
singletonObject
, store all created singleton beans (complete beans, that is, instantiation has been completed and attribute filling has been performed). -
earlySingletonObjects
, store beans that are instantiated only, but are not filled and initialized attributes. -
singletonfactories
, store the factory that can create beans. Through this factory, beans can be obtained and bean generation can be delayed. The beans generated by the factory will be placed in earlySingletonObjects.
Instantiate beanbackSpring does not know whether the current bean has circular dependencies, it will resolutely go toThe current bean is stored in singletonfactoriesFactory, this step is to expose it in advance
Then start property injection. At this time, bean A finds that it is necessary to inject bean B, so please execute getBean(B)
- First go to singletonObject to find out if there is, and if there is, return it
- If not, it will determine whether the bean is being created. If not, it will return null
- If it is being created, go to earlySingletonObjects to find it, and if there is, return it
- If not, go to singletonfactories to find the bean's factory, create the bean through the factory, and store it in earlySingletonObjects
- If singletonfactories does not find the bean's factory, return null
- If null is returned, it means that the bean has not been created yet. At this time, the bean will be marked as being created, and then the doCreateBean will be called (that is, three steps: instantiation, attribute filling, and initialization)
At this time, it is time to inject the bean property of B, and getBean(A) is called. A finds the factory exposed in the singletonfactories and reaches A, and then deletes A from the singletonfactories and puts it in earlySingletonObjects.
At this time, the B attribute is injected successfully, and then initializes it, and finally B is stored in singletonObject.
At this time, we returned to the place where A injected B, and completed the injection of B, and then A was also deleted from earlySingletonObjects and stored in singletonObject.
Summarize
The above is personal experience. I hope you can give you a reference and I hope you can support me more.