Spring IOC principle

Container initialization

The initialization of the container is first performed in the corresponding constructor. In the implementation class constructor of applicationContext, first we deal with the setConfigLocations in the parameter path, replace it with the system variable (the refresh method), and then call the refresh method (this is the initialization method of the most core container).

1. Resource positioning:

In the refresh method, calling the obtainFreshbeanfactory method tells the subclass to refresh beanfactory (which is called refreshbeanfactory refresh and getbeanfactory gets the refreshed factory back). In the refreshbeanfactory refresh process, if the factory already has a, create a new factory, where loadbeandefinitions is the method of loading bean definitions.

Create the implementation class of beandefinitionreader in the loadbeandefinitions method, call its loadbeandefinitions method (this method is an overloaded method, with parameters of resource or string path, and getconfigresources method (null is returned by default, and the subclass is overridden, such as classpathxmlapplicationcontext class) And getconfiglocations methods to obtain the resource set and the resource path set (generally one is empty, generally setting the parameter path of the container to configlocations, and the classpathxmlapplicationcontext has a constructor that directly generates the classpathresource set from the parameter path without setting configlocations, and sets it to configresources), In fact, after locating the resource, the overloaded method with path as the parameter will also call loadbeandefinitions with resource as the parameter to parse and load beandefinition. This is the second step (described below).

In the loadbeandefinitions (path parameter) method of beandefinitionreader, load in two ways according to the resourceloader type (locate multiple resources in one path in ant regular expression mode (such as pathmatching resourcepattern resolver) or locate one resource in the default mode (ApplicationContext inherits the defaultresourceloader implementation mode), Call getresource of resourceloader respectively (build classpathcontextresource starting with /, and build classpathresource starting with classpath without classpath. If it is not, try to build urlresource. If the construction fails, call getresourcebypath, a specific ApplicationContext implementation class, to build a specific resource, such as filesystemxmlapplicationcontext is filesystemresource) or getresources (the regular method of pathmatching resourcepatternresolver is not described in detail here) complete the resource location.

2. Parse and load beandefinition from resource:

Similarly, in BeanDeFinitionReader's loadBeanDeFinitions, after calling the getResource of resourceLoader, get Resource, call resource (resource) as a parameter loadBeanDeFinitions (an interface method is implemented for subclasses, because different reader loading resource way is different) loading BeanDeFinition.

For example, xmlbeandefinitionreader is an IO operation on an XML file (add the resource to be processed now to the resource collection being processed by the current thread). First, take out the InputStream from the resource, package it into an inputsource, and call its own doloadbeandefinitions method.

In the doLoadBeanDeFinitions method, calling the doLoadDocument method to wrap it into Document----- is to use validationMode (the default is auto check mode, meaning if it does not show the way to define the check, use XSD mode) and DocumentLoader (the default is DefaultDocumentLoader in XmlBeanDeFinitionReader). Call the loaddocument method of documentloader with other parameters to encapsulate the resource into a document class (the specific encapsulation method is not introduced. Those interested can learn about it by themselves. It is done in the builder mode) and call the registerbeandefinitions method to parse the loaded bean.

The registerbeandefinitions method is to use registerbeandefinitions of beandefinitiondocumentreader to specifically parse and load each label of each element in the document (tree structure, starting from root (that is, beans label). If it is a bean tag, the parsebeandefinitionelement method of beabdefinitionparserdelegate parses the information of the XML element according to the bean rules of spring (property parsing, in which value and ref are parsed in different ways. If value is used to construct typedstringvalue, if ref is used to construct runtimebeanreference, which will be used later in dependency injection, as well as ID, name, and other attribute parsing) the encapsulated beandefinitionholder (including beandefinition and beanname) of the obtained beandefinition (here is the meaning of identifier. If there is ID, ID is used as the identifier, if there is no ID, the first alias in the name attribute is used as the identifier) and alias list (the content in the name attribute, if there is no ID, the first alias in the name is not used as the alias, but an identifier)) to register beans in the next step (beandefinitionreaderutils. Registerbeandeffinition).

Other tags such as import and alias can be understood from the source code.

3. Registration of beandefinition in IOC container

BeanDeFinitionReaderUtils. Registerbeandefinition registers beanname and beandefinition with the registerbeandefinition method of beandefinition Registry (defaultlistablebeanfactory) (that is, add beanname to the set of beanname of a registered bean, and then put it into the map of beandefinition corresponding to beanname. If overwriting is not allowed and there is a beanname with the same name, an error will be reported). Register the beanname and alias list with the registeralias method of beandefinitionregistry (put it into a map of beanname corresponding to alias, and remove if there is an alias that is the same as beanname).

IOC container dependency injection

1、getBean

The bean that calls lazy init for the first time is triggered with the getBean method of beanfactory as the entry (implemented in the abstractbeanfactory implementation class). If it is a single instance, it will be cached and loaded only once. If it is a special bean such as a factorybean, it will pass the instance of the bean into the getobjectforbeaninstance method to obtain the bean generated by the factorybean (call the GetObject method of the factorybean, which is the method to be rewritten by the custom factorybean. This is also the principle of AOP. See the AOP analysis below for details). When loading for the first time, first judge whether the beandefinition exists in the current beanfactory. If not, find it from the parent beanfactory and recurse all the time.

After finding it, verify whether there is a recursive dependency. If there is an error, set the dependency of the current bean to two maps (one is the dependent map and the other is the dependent map), where:

The createbean method is the method to generate beans and handle some initialization, such as init method attribute and post processor. In the method, judge whether there is a post processor before instantiation. If there is such a processor, short circuit the creation of the specified bean and directly return a proxy instead of the specified bean (this processor can specify to generate an object of other types). If not, use docreatebean to create a bean and return.

Docreatebean uses createbeaninstance to generate beanwrapper (wrapper bean), and then populatebean is used to inject dependent beans into the beans (autowire, etc.).

Createbeaninstance creates beanwrappers in three categories:

Populatebean injects the generated bean dependency. First, process the non simple type property with autowire, judge whether this property is in the property when parsing and loading beandefinition. If so, after getBean initialization, put it into the propertyvalue collection (this is the encapsulation of propertyname and value), and then update the dependency map, Then inject non autowire or general attributes. Those to be transformed need to be transformed by valueresolver (if the runtimebeanreference is configured as ref in the XML before loading, get the getBean (if it is taken from the parents in the parent beanfactory), and then put it into the propertyvalue collection, and update the dependency map). Finally, it is injected into the bean. The injection mentioned here actually occurs in the setpropertyvalue (propertyvalue Collection) method of the last beanwrapper. The specific implementation is to obtain the setter method assignment through reflection.

2. Lazy init = = false initialization (only for singleton, which is also the default mode)

Initialize in the finishbeanfactoryinitialization method in the refresh method (actually calling the getBean method).

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>