Note 1: spring source code is based on spring3.1
NOTE 2: Refer to spring technology insider Version 2
We have analyzed the steps of resource locating and loading and parsing of beandefinition during IOC container initialization. Now we can analyze the loading and parsing of beandefinition, spring registers the parsed beandefinition to the IOC container.
After beandefinition is loaded and parsed, beandefinition information has established its own data structure in the IOC container, but the data cannot be directly used by the IOC container, you must register the beandefinition data in the IOC container. In defaultlistablebeanfactory, beandefinition is held by a member variable beandefinitionmap of the hashmap type. You can see the following in the source code section of defalistlistablebeanfactory:
/** List of bean definition names, in registration order */private final List
beanDefinitionNames = new ArrayList
();/** Map of bean definition objects, keyed by bean name */private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
The process of registering the parsed beandefinition to beandefinitionmap in the IOC container is completed after loading beandefinition. The previous analysis focused on loading and parsing beandefinition, but did not analyze beandefinition to the branch of IOC container. See the following code:
Protected void processbeandefinition (element ele, includelegate) {// The specific resolution is delegated to the handler to complete // beandefinitionholder is the beandefinition encapsulation class, which encapsulates the beandefinition and bean name and alias, use it to register with the IOC container. beandefinitionholder bdholder = delegate. parsebeandefinitionelement (Ele); If (bdholder! = NULL) {bdholder = delegate. decoratebeandefinitionifrequired (Ele, bdholder); try {// register the parsed beandefinition with the IOC container. beandefinitionreaderutils. registerbeandefinition (bdholder, getreadercontext (). getregistry ();} catch (beandefinitionstoreexception ex) {getreadercontext (). error ("failed to register bean definition with name'" + bdholder. getbeanname () + "'", ELE, ex);} // After the beandefinition registration is complete, send the event. getreadercontext (). firecomponentregistered (New beancomponentdefinition (bdholder ));}}
In the above Code, the first code of the method is to call the parsebeandefinitionparserdelegate parseandefinitionelement method to parse the <bean> label and return the beandefinitionholder object, this object holds beandefinition, bean name, alias, and other information, which is the focus of the previous analysis. The following code registers beandefinition with the IOC container and calls the registerbeandefinition method in the beandefinitionreaderutils tool class, pass the previously parsed beandefinitionholder and IOC container object (defaultlistablebeanfactory class implements the beandefinitionregistry Interface) as parameters to the method.
Next we will follow the code to see how registration occurs.
The registerbeandefinition method in the beandefinitionreaderutils class:
Public static void registerbeandefinition (beandefinitionholder definitionholder, beandefinitionregistry registry) throws beandefinitionstoreexception {string beanname = definitionholder. getbeanname (); // register beandefinition registry with the IOC container. registerbeandefinition (beanname, definitionholder. getbeandefinition (); // If the parsed beandefinition has an alias, register the alias with the container. string [] aliases = definitionholder. getaliases (); If (alias Es! = NULL) {for (string aliase: aliases) {registry. registeralias (beanname, aliase );}}}
The code above shows that beandefinition registration is actually completed by the beandefinitionregistry's registration method, while the defaultlistablebeanfactory class implements the beandefinitionregistry interface, so the real completion of beandefinition registration is exactly the defaultlistablebeanfactory class.
Defaultlistablebeanfactory source code:
Public void evaluate (string beanname, beandefinition) throws evaluate {// If (beandefinition instanceof abstractbeandefinition) {try {(response) beandefinition ). validate ();} catch (beandefinitionvalidationexception ex) {Throw new beandefinitionstoreexception (beandefinition. getresourcedescription (), beanname, "valida Tion of bean definition failed ", ex) ;}// thread synchronization is required during the registration process to ensure data consistency synchronized (this. beandefinitionmap) {// check whether a beandefinition with the same name has been registered in the IOC container. If the registered bean is not allowed to overwrite the registered bean, an exception object oldbeandefinition = This is thrown. beandefinitionmap. get (beanname); If (oldbeandefinition! = NULL) {If (! This. allowbeandefinitionoverriding) {Throw new beandefinitionstoreexception (beandefinition. getresourcedescription (), beanname, "cannot register bean Definition [" + beandefinition + "] for bean '" + beanname + "': there is already [" + oldbeandefinition + "] bound. ");} else {If (this. logger. isinfoenabled () {this.logger.info ("overriding bean definition for bean '" + beanname + "': replacing ["+ oldbeandefinition +"] with ["+ beandefinition +"] ") ;}} else {// you have not registered beandefinition with the same name, and saved the bean name to beandefinitionnamesthis. beandefinitionnames. add (beanname); this. frozenbeandefinitionnames = NULL;} // store beandefinitionmap with beanname as the key and beandefinition as the value. If beandefinition has the same name, it will overwrite it. this. beandefinitionmap. put (beanname, beandefinition); resetbeandefinition (beanname );}}
Beandefinition registration to the IOC container is completed here. After all beandefinition registration is completed, the IOC container initialization process is completed. At this time, the configuration information of the entire bean has been created in the IOC container defalistlistablebeanfactory, and these beandefinition can be used by the container, and they are all maintained in beandefinitionmap. The container is used to maintain and process the bean information, which is the basis for setting up control inversion for the container.