Spring supports circular references by default with singletons
The two classes refer to each other (cyclic dependencies). Spring allows such cyclic dependencies in the case of singleton, non-constructor injection
Spring’s loop dependencies can be turned off
1. APi provided by Spring 2
Cyclic dependencies are nothing more than property injection Spring’s property injection is part of the spring bean’s life cycle
Two related concepts:
1. Spring Beans — Objects managed by the Spring container that may have gone through the full Spring lifecycle (why is it possible? Are there any beans that don’t go through the bean life cycle? The answer is yes), which ultimately resides in the Spring container; A bean must bean object.
Object – Any instantiated object that complies with Java syntax rules, an object does not have to bea Spring bean. The life cycle of a bean is the process of scanning a class on disk, instantiating it, initializing it, and then putting it into a container.
The life cycle of a Spring bean goes through steps
1: instantiate an ApplicationContext object; 2: Call bean factory post-processor to complete scanning; 3: cyclic parsing of scanned class information; 4: Instantiate a BeanDefinition object to store parsed information; 5. Put the beanDefinition object into beanDefinitionMap for later bean instantiation. 6: Call the bean factory post-processor again; 7: Of course, Spring does a lot of things, like internationalization, like registering BeanPostProcessor, If we only care about how to instantiate a bean, so this step is called spring finishBeanFactoryInitialization methods to instantiate singleton beans, spring to do before instantiating validation, need to traverse all scan out of class, Check whether the bean is Lazy, prototype, abstract, and so on. If you need to infer the constructor before you instantiate a bean, you need to know which constructor to use because spring instantiated objects are reflected through constructors; Spring calls constructor reflection to instantiate an object after inferring the constructor; Notice that we’re talking about objects, objects, objects; At this time, the object has been instantiated, but it is not a complete bean. The simplest embodiment is that the instantiated object property is not injected, so it is not a complete bean. 10: Spring handles the merged beanDefinition(merged? Is a very important part of Spring, which will be discussed later); [singletonFactories] [singletonFactories] [singletonFactories] Determine whether property injection needs to be completed 13: If property injection needs to be completed, start property injection 14: Determine bean type callback Aware interface 15: invoke lifecycle callback method 16: Complete proxy if needed 17: Put to the singleton pool — bean completion — in the Spring container
When does Spring instantiate beans
Spring in AbstractApplicationContext# finishBeanFactoryInitialization method completed the bean instantiation. That’s something to keep in mind
Process theory for Spring Bean instantiation:
Assuming that there are classes X and Y on disk, when Spring starts up, it will scan to see that X and Y are annotated (@autoWired) and then encapsulate the class information of X and Y into a beanDefinition object, which contains the information of the current class. Information such as whether the current class is abstract, the description of the current class, the current class type, whether the current class is lazy to load, and so on. Once wrapped, the beanDefinition object is put into a Map collection and beanFactoryPostProcessor (extension) is executed if any. Then start the validation. If all the validation passes, call the prelnstantiateSingletons method (quite a complicated process) to instantiate the current class, which then becomes a Spring bean into the singleton pool.
Source code validation:
This code is used to initialize the Spring container. When this code is finished executing, XY has been instantiated
BeanFactory ->beanDefinitionMap does not yet have classes X ory
Scan the concrete implementation code
Put the beanDefinitionMap
Too many calls
Look at the source code in AnnotationConfigApplicationContext class parent class defines the beanFactory
This is the beanFactory we often say spring bean plant It is DefaultListableBeanFactory instance
In DefaultListableBeanFactory has an attribute called beanDefinitionMap solve concurrent ConcurrentHashMap 1.7, 1.8
After beanDefinitionMap invokeBeanFactoryPostProcessors method found in the x, y Therefore nvokeBeanFactoryPostProcessors finished scanning the class into a beanDefinition object (note that this time the spring not to instantiate the bean)
But in finishBeanFactoryInitialization instantiation singleton beans
Rear BeanFactoryPostProcessors: bean factory of processor can interfere with the spring bean factory initialization process? Extension: you can do some things before and after initialization to implement this interface you can take the beanFactory you can make some changes to the beanFactory, etc
Focus on call: finishBeanFactoryInitialization method the beanFactory. PreInstantiateSingletons ();
Get the beanNames set for traversal
Why there is a beanDefinition:
The code used to describe the Spring bean contains all the information about the Spring bean (because ordinary classes cannot describe scope lazy, etc.). A call to the doGetBean ac.getBean is the underlying call to the doGetBean method
SingletonObjects: singleton pool
Key code before creating the bean
SingletonsCurrentlyInCreation is creating the singleton bean name collection In this collection
The key code calls the passed ObjectFactory<? Lambda is the method of singletonFactory
And then we go down and we go here
This bean has not been created yet
Create an object
Go inside the method in turn
The object is not instantiated as a bean
AllowCircularReferences defaults to true
Spring handles the three maps involved in loop dependencies
The injected properties have values after executing this method
Next, call the initializeBean method
// Implement part of the Aware interface
Callback to the lifecycle method
Lifecycle callback initialization methods can be implemented in three ways simultaneously in a bean because execution timing is different in the source code
The spring bean’s lifecycle calls the procedure
Will be created alphabetically (can be changed)
Loop dependency!
X property injection fill y is definitely not available when called to doGetBean(“y”)
Is creating the process of creating x y so singletonsCurrentlyInCreation have x
X and Y are being created
Y has not been created before this method is executed. Once the console is finished, print y
At this point y is injecting X so go back to getBean(“x”)
Key code: it must not return null. If null is returned, it will be an infinite loop that will create x again
(Take X from the singleton pool but X is definitely not in the singleton pool because it has not run out of bean life)
Note that the second argument to getSingleton is dead true
Singleton pool – Level 1 cache mainly holds singleton beans (so called containers). Now go to fetch x from the singleton pool and return NULL
This checks if x is being created true
I still can’t get it here and the reason for that is very simple, because there’s no net in front of it and this map is in the level 3 cache
This is definitely true
This is where you can get it but this is not of type X it’s Factory
Question: 1. How did the factory come? 2. Why not just store an X in level 2 cache instead of a factory? 3. How is X related to the factory? 4. Is the x manufactured by the factory the same as the X being created? 5. Do beans that are not loop-dependent perform level 3 caching? Answer: No answer 1: is related to the bean’s life cycle, as shown below
Answer 2: Because if Spring stores x directly into the level 2 cache, then when y injects X, it needs x that is not currently stored in x
Answer 4: The default is the same
(x depends on y, y depends on x, x depends on z, x depends on x, x does not need to be repeatedly generated from the factory) For gc recycling singletonsCurrentlyInCreation 80% of this collection is used for circular dependencies
BeanDefinition A class unannotated
And then trying to get a from ac will definitely get an error because A is not in the Spring container
Call the programmer or the spring of all postProcessors / / get all of the spring spring BeanFactoryPostProcessor object performs postProcessBeanDefinitionRegistry method The scan that’s done, when it’s done, it becomes a beanDefinition
The so-called scanning of the subclass is inside the spring spring BeanFactoryPostProcessor postProcessBeanDefinitionRegistry complete scanning method
How do you distinguish between what spring provides internally and what the programmers themselves provide? Find all the subclasses that implement the interface, and look twice, the code is pretty much the same: first look inside Spring itself and second look for programmers to write
Spring extension point
For example: change the class to A, now you can get A and B can not get
Write at the back:
I am an ordinary worker of YC engaged in software development industry, working for many years to write a technical blog for the first time. This is also something I have learned, do a share! Thank you again, Zi Lu teacher, his source code of things very in-depth and meticulous. I also made a summary after listening to his class. Thank you again!