Shock! ! ! ! The whole Java dare not give you the information

  1. IOC Overview
    1.1 What is it?
    Two concepts: inversion of control, dependency injection,
    look at the traditional way of working: Based on the principle of object single responsibility, an object rarely completes its own work without relying on other objects, so objects will appear at this time Dependence between. What is reflected in our development is that when we need any object, we create what object. At this time, the control over the creation of the object is in our own hands. When too many objects are created, an object change will occur, and all the objects that depend on it have to be changed, which is highly coupled. At the same time as autonomy is manifested, there is also serious object coupling. In terms of spring, the editor also compiled a set of spring family bucket study notes, which contains a summary of the hottest spring issues on the entire network.

At this time, we will think about whether we can directly get the object to use when we use it, and give the ability to create the object to a third party, so that we don't need to care about how the object is created. About to hand over control of oneself. This is the inversion of control. At
this time, there will be another problem, how can the object be directly used by us. When the object is created, we inject the object into this object, and then it can be used. This is dependency injection.
Another problem, how can the coupling be solved? Through the inversion of control, we only use this object. If the object is modified, we only need to modify the way the third party creates the object. Is there still so-called object coupling at this time?

  1. IOC architecture
    Insert picture description here

A picture is done, this is the IOC's architectural idea, this is not its execution flow chart.
Let's interpret it step by step.
2.1 Vernacular Version
In the first chapter, we learned that IOC is to help us manage and create objects.
At this time we need a container to carry the information we need to create, that is, the XML or annotations in the figure, then after we have our own BeanDefiniton information, we need an interface to read this information, so BeanDefinitionReader appears to read Our own Bean information.
Then we need to consider a question, how to produce so many objects?
The answer is the factory model. Spring's default factory is DefaultListableBeanFactory, yes, all objects in Spring (container objects and objects created by ourselves) are created by him. Mass production of objects At
this time, there is another problem. We don't want to directly produce them through BeanFactory. We need to perform some specific processing on this factory. So BeanFactoryPostProcessor appears, which is used to do some specific processing on the factory. We can customize BeanFactory by implementing this interface. Another brother said: I want to create some objects that I like separately, arrange, FactoryBean was born, it can help us create an object we need (the fourth part explains the difference between them in detail).
Then another brother said: I want to make a unified object perform some special behaviors in my way before creating a unified object, simple, arrange: see_no_evil
BeanPostProcessor appeared, he provides two methods: one after the object is instantiated, before the initialization, Execute the internal Before method, after initialization, execute the After method. (Bean life cycle, detailed explanation of the fourth part)
At this time, some brothers have questions. Didn't it mean that the BeanPostProcessor is executed before the object is created? How is the Before method that is executed after the creation is completed.
If you guys have understood the concept of instruction reordering, then you must have heard of a case where it takes three steps to create an object

Create space (instantiate),
initialize and
assign

Among them, instruction reordering occurs during initialization and assignment.
According to this point, it should be possible to get to a point, and instantiation and initialization are different.
So it leads to another point, we have to perform some operations on the Bean, how to do it, it must be to modify the attributes, or add some attributes, etc., we need to wait for it to open up space in the heap, that is, to execute it after the instantiation is completed.
So the before method of BeanPostProcessor is executed after instantiation and before initialization.
After a lot of previous operations, finally our object entered our pocket (in the container).
Regarding destruction, under normal circumstances, we cannot get its destruction method through ApplicationContext, but can only be obtained through its subclasses. Regarding the destruction of the same process, first perform an operation before destruction, and then destroy it.
Among them, instruction reordering occurs during initialization and assignment.
According to this point, it should be possible to get to a point, and instantiation and initialization are different.
So it leads to another point, we have to perform some operations on the Bean, how to do it, it must be to modify the attributes, or add some attributes, etc., we need to wait for it to open up space in the heap, that is, to execute it after the instantiation is completed.
So the before method of BeanPostProcessor is executed after instantiation and before initialization.
After a lot of previous operations, finally our object entered our pocket (in the container).
Regarding destruction, under normal circumstances, we cannot get its destruction method through ApplicationContext, but can only be obtained through its subclasses. Regarding the destruction of the same process, first perform an operation before destruction, and then destroy it.
2.2 The actual work process
Anyone who has read the Spring source code or heard it knows that there is a method called refresh, which has accomplished a lot of things. Of course, his behavior also represents the entire process of loading and instantiating objects in the IOC container. Let's take a closer look in the code interpretation of Chapter 3Insert picture description here

Implementation process:

Load the configuration file and initialize the system environment Environment interface.
Prepare the context environment and initialize some configuration resources.
Create a factory.
Add various environments to the factory.
Obtain the subclass's own rewritten BeanFactoryPostProcessor
execution container and our own BeanFactoryPostProcessor
registration BeanPostProcessor
internationalization processing
relay
subclass Initialize the Bean to
register the listener, and
complete the Bean creation in the observer mode.
Publish the corresponding events and listeners.

  1. IOC source code interpretation
    3.1 Context configuration start
    Insert picture description here

When ClassPathXmlApplicationContext was created, these methods were executed in the constructor.
To put it bluntly, a loader that parses the configuration file path is loaded; then the configuration file is obtained through the system environment variables, and some configuration files are removed from spaces, conversion expressions, and so on (without parsing); the last is the I marked it in red, and it did almost all the work in the refresh method. Let's talk about
3.2 refresh

This method almost completes all operations, creating factories, executing Processors, etc., instantiating objects, opening event monitoring, and so on.
Next,
let's talk about 3.3.1 prepareRefresh()
The main function of this method is to do some preparatory work for the refresh of the application context. Check the resource file, set the startup time and active status, etc.
3.3.2 obtainFreshBeanFactoryInsert picture description here

You can get it. It is mainly to create a factory BeanFactory, parse the configuration file, and load the Bean definition information (just answer this point during the interview, if you want to say, you can load the bean information below to chat) Yes, the ones marked in red are the points we will talk about nextInsert picture description here

This is the process of loading the configuration file. Note: There is still no analysis at this time, and the analysis is below the red oneInsert picture description here

This is the reading process. The specific analysis process comes from parse. This directly calls the class library for parsing XML in Java. If you are interested in reading it yourself, it finally returns a Document object.
Through the Document object, read the internal tags and execute different methods. The logic is the same as the idea of ​​parsing the configuration file in MyBatis. You can read it yourself.
At this time, all Bean definition information is saved to the BeanDefinitionRegistry interface, and then the registration method of the subclass DefaultListableBeanFactory factory is takenInsert picture description here

3.3.3 prepareBeanFactory(beanFactory)
prepares some environment for BeanFactory, which is convenient to use when instantiating, and at the same time add the container's own BeanPostProcessor
Insert picture description here

3.3.4 postProcessBeanFactory is
reserved for subclasses to extend BeanFactoryPostProcessor,
3.3.5 invokeBeanFactoryPostProcessors(beanFactory)
This class involves two interfaces.

BeanFactoryPostProcessor
BeanDefinitionRegistryPostProcessor interface, this interface is a sub-interface of BeanFactoryPostProcessor, its priority is higher than BeanFactoryPostProcessor

Its overall execution process is: first execute the BeanFactoryPostProcessor of BeanDefinitionRegistryPostProcessor, and then execute BeanFactoryPostProcessor. The
following figure shows the processing process of the BeanDefinitionRegistryPostProcessor interface
Insert picture description here

The
overall logic of BeanFactoryPostProcessor processing logic is to classify first, skip the ones that have been processed, and the classification processing logic for those that have not been processed. The logic is the same as above.
3.3.6
The logic of the registerBeanPostProcessors method is the same as the above, except that the above is directly executed BeanFactoryPostProcessor, and this is only registered but not executed.
Insert picture description here

First get all the BeanPostProcessor type Beans in the factory, then classify and process, sort and register.
3.3.7 initMessageSource()
executes internationalized content
3.3.8 initApplicationEventMulticaster
creates a multicaster to provide support for adding Listener.
Main logic:

Whether there is an applicationEventMulticaster in the container, if it exists, register
it directly. If it does not exist, create a SimpleApplicationEventMulticaster and register it in the container.

3.3.9 onRefresh()
subclass extension
3.3.10 registerListeners()
implementation of observer pattern
Insert picture description here

3.3.11 finishBeanFactoryInitialization

There is too much content in this part, so I use code and diagrams to explain it.
Insert picture description here

The following figure is the main process of creating Bean
Insert picture description here

According to the serial number in the figure one by one:

Whether BeanDefinition needs to be merged. BeanDefinition encapsulates the Bean into different Bean information definition classes according to different types of configuration file information. For example, the GenericBeanDefinition of our commonly used configuration file version; ScannedGenericBeanDefinition of the annotation scan version and so on.

And in this process, the parent definition and the child definition need to be merged when actually processing the definition information, mainly in the following three aspects

There is parent definition information, use the parent definition information to create a RootBeanDefinition, and then pass in the custom information as a parameter.
There is no parent definition information, and the current BeanDefinition is of type RootBeanDefintion, directly return a clone of RootBeanDefintion
There is no parent definition information, and the current BeanDefintion is not of type RootBeanDefintiton, directly construct a RootBeanDefintion through the BeanDefintion to return

The above process is also the execution process in the source code
Insert picture description here

isFactoryBean. Determine whether it is a FactoryBean

** Brief introduction: ** FactoryBean allows developers to create their own Bean interface. Three methods are provided internally
Insert picture description here

When we use GetBean directly to the Bean, what we get is the Bean type specified by the factory to return. If you want to get the Bean itself, you need to get it with a prefix &
Insert picture description here

Let’s look at one more point. This is the main way to get Bean from the container, and it is also the logic to solve circular dependencies.

Let’s talk about how it solves circular references?
It introduces the concept of a three-level cache
Insert picture description here

When a circular reference occurs, it first creates the Bean through the ObjectFactory factory. **At this time, the object does not carry out attribute assignment, but only opens up space in the heap. **Then add the Bean at this time to the earlySingletonObjects container, which means that the Beans stored in this container are semi-finished products. **In the subsequent attribute assignment, since the object is a singleton, its reference address will not change, that is, the object is ultimately complete.
1. getBean. Through this method, all objects are directly created. This is also the core method of Spring. Let’s take a look at its overall process.
Insert picture description here

Its main logic is:

First get the real name of the Bean to be instantiated, mainly to process the FactoryBean. After getting it, check whether the Bean has been created in the current container, and return directly if it exists.
If it does not exist, get its parent factory. If the parent factory is not empty and the current Bean information does not exist in the current container, try to get the Bean definition information from the parent factory and instantiate the Bean.
If the parent factory is empty, the current Bean information is stored in the alreadyCreated cache.
Get the merged information (getMergedLocalBeanDefinition) of the current Bean, check whether the current Bean has dependencies, if it exists, determine whether the current Bean and the dependent Bean are circular dependencies, if not, create the dependent Bean first to
determine the scope of the current Bean.
If the current Bean is a singleton object, create a Bean instance directly.
If the current Bean is a multi-instance object, add the current Bean information to the multi-instance cache being created, and remove
it after creation. If the current Bean is of another type, such as Requtst, Session, etc. Type, customize an ObjectFacotry factory, rewrite the getObject method, create an object After the
object is created, determine whether the current object is the object you need, if it is returned directly; if the type conversion is not performed, if the type conversion fails, an exception will be thrown directly

Next, take a look at the execution of CreateBean
Insert picture description here

The main thing this method accomplishes is: get the corresponding Class object by the name of the Bean; if the Class object obtained by the current Bean is not empty and the RootDefintiton can directly obtain the Bean, clone a copy of the Bean definition information for later use .
Verify the @Override information on the current Bean. Execute BeanPostProcessor and return a proxy object (if there is a proxy), if there is no proxy, create the Bean directly.
Next, let’s talk about this stuff-resolveBeforeInstantiation
Insert picture description here

Come on, go ahead and take a look at the preprocessor logic
Insert picture description here

The post processor did not look at it, it called all the post processors, and then executed it again, without other logic.
Next to continue our topic: doCreateBean
Insert picture description here

The general process is as shown in the figure above:
first judge whether it is a singleton in the future, and then check whether there is a Bean being created from the FactoryBean cache, if it exists, take it out, if it does not exist, create a wrapper class instance of the current Bean. Then get the instance and instance type of this class, and execute the post processor.
Whether the current Bean is a singleton and whether circular dependencies are allowed, it is being created at the time. If it is, create an ObjectFactory of the current Bean to solve the problem of circular dependencies.
Fill in the properties of the Bean and instantiate the Bean.
Check the early container cache (whether the bean is in the second-level cache in the cache). If it does, it means that there is a circular dependency, so deal with
it. Let’s look at the circular dependency first.Insert picture description here

Next, createBeanInstance
Insert picture description here

Spring provides three ways to create object packaging:

Create directly through the supplier object. obtainFromSupplier
is created directly through the factory method.
Created by default. Whether the construction method needs to be automatically injected The construction method does not need to be automatically injected, and the default construction method is called

After this method is executed, one thing you should know is that the object instance has been created at this time, and the rest is to execute a series of enhancers and initialization methods, attribute filling, and so on.
We follow the order of code execution, attribute filling is
the execution logic of populateBean method:

First judge whether the passed in Bean is null, if it is null, judge whether there is an attribute value in the Bean definition information, if it exists, it is abnormal; if it does not exist, skip the
current Bean definition information whether it is merged, if it is and at this time There are InstantiationAwareBeanPostProcessors in the factory, then modify the Bean information before the attributes are filled.
Get all the attribute values, analyze the automatic injection method of attribute values, Type or Name, and perform automatic injection.
Determine whether there is InstantiationAwareBeanPostProcessors, modify the attributes set before, and
determine whether they exist Dependency check, check dependency
attribute assignment

Insert picture description here

Next, look at the implementation of the initialization method, which is to call the BeanPostprocessor, init and other methods
Insert picture description here

This is the execution flow chart of this method. I believe that at this place, everyone should understand why the before method of BeanPostProcessor is executed in the init method. The function of this method is only for printing a life cycle, the object has been created before.

Next, let's look at the method of destruction. registerDisposableBeanIfNecessary
For singleton beans, Spring stores the beans that need to be destroyed in the disposableBeans cache, and encapsulates the destroyed Bean through DisposableBeanAdapter.
For other scopes, it customizes the destruction callback function, but in the end it is encapsulated as DisposableBeanAdapter and
encapsulated as DisposableBeanAdapter. In the process, it will first determine whether there is a destroy method in the Bean, and then assign a value to the destroyMethodName variable. Judge the parameters of this method again, if the number of parameters is greater than 1, an exception will be thrown
Insert picture description here

3.3.12 The finishRefresh
method performs a series of resource cleaning and
Insert picture description here

initLifecycleProcessor, this method is very simple, just look at whether there is a lifecycle processor in the current Bean, if it exists, use this directly, if it does not exist, create a default one, and register it as a singleton and throw it into the container, today’s copy Reader benefits: forward + follow to get the microservice family bucket study notes compiled by the editor!
Finally, I
like the editor's sharing today, remember to follow me and like it, thank you for your support! The important thing is said three times, forward + forward + forward, be sure to remember to forward and follow! ! !

Guess you like

Origin blog.csdn.net/dcj19980805/article/details/115005569