IOC of the Org.springframework.beans

Source: Internet
Author: User
Tags aliases

Objective

In general, the application code needs to tell the container or framework to find the class that it needs, and then the application code creates an instance of the object to use. Therefore, the application code needs to create an object instance before using the instance. However, in IOC mode, the task of creating an object instance is given to the IOC container or framework (spring's configuration file) so that the application code only needs to use the instance directly, which is the IOC.

Dependency injection and control inversion are the same concept. What it means is that when a role (possibly an instance, the caller) needs the assistance of another role (another instance, the callee), the caller's instance is typically created by callers during the traditional program design process. In spring, however, the work of creating the callee is no longer done by the caller, so called control inversion, and the work of creating the callee instance is usually done by the spring container, which is then injected into the caller and, therefore, also called dependency injection. Whether it's dependency injection or control inversion, spring is a dynamic, flexible way to manage a variety of objects.

Container: In spring, Org.springframework.beans.factory.BeanFactory is the actual representative of the spring IOC container, the IOC container is responsible for accommodating the bean described earlier and managing the bean.
Instantiate a container:
ApplicationContext context=new classpathxmlapplicationcontext ("Applicactioncontext.xml");
Beanfactory factory= (beanfactory) context;

Xmlbeanfactory, which is the bottom-level implementation of the container family, has a very obvious feature compared to the contexts we use in spring applications, and it provides only the most basic IOC container functionality. As can be seen from its name, this IOC container can read beandefinition defined in XML form. Understanding this helps us to understand the difference and connection between ApplicationContext and the basic beanfactory. We can assume that the direct beanfactory implementation is the basic form of the IOC container, and that the implementation of the various applicationcontext is a high-level representation of the IOC container.

     Post xmlbeanfactory source
Package org.springframework.beans.factory.xml; import Org.springframework.beans.BeansException; Import Org.springframework.beans.factory.BeanFactory; Import Org.springframework.beans.factory.support.DefaultListableBeanFactory; Import Org.springframework.core.io.Resource; public class Xmlbeanfactory extends Defaultlistablebeanfactory {private final Xmlbeandefinitionreader reader = new Xmlbea Ndefinitionreader (this); Public xmlbeanfactory (Resource Resource) throws Beansexception {This (Resource, null);} public xmlbeanfactory (Resource R Esource, Beanfactory parentbeanfactory) throws beansexception {super (parentbeanfactory); This.reader.loadBeanDefinitions (Resource); }}
     as can be seen from the source code, in the Xmlbeanfactory construction method, the need to resource object, the Xmlbeandefinitionreader object initialization, The Loadbeandefinitions method is then called, which initiates the process of loading beandefinitions from the resource, which is also an important part of the IOC container initialization.
  

The initialization of the IOC container includes the three basic processes of beandefinition resouce positioning, loading, and registration.

This.reader.loadBeanDefinitions (Resource); we go in Xmlbeandefinitionreader source to find the Loadbeandefinitions method

public int loadbeandefinitions (Resource Resource) throws Beandefinitionstoreexception {//Here is the entrance to the call. Enter the following method return Loadbeandefinitions (New Encodedresource (Resource)); } public int loadbeandefinitions (Encodedresource encodedresource) throws Beandefinitionstoreexception {Assert.notNull (Encodedresource, "Encodedresource must not being null"); if (this.logger.isInfoEnabled ()) {This.logger.info ("Loading XML bean Definitions from" + Encodedresource.getresource () ); } Set currentresources = (set) This.resourcesCurrentlyBeingLoaded.get (); if (currentresources = = null) {currentresources = new HashSet (4); This.resourcesCurrentlyBeingLoaded.set ( Currentresources); } if (!currentresources.add (Encodedresource)) throw new Beandefinitionstoreexception ("detected cyclic loading of" + Enco Dedresource + "-Check your import definitions!"); try {//Here get the XML file and get IO InputSource ready to read. InputStream InputStream = Encodedresource.getresource (). getInputStream (); try {inputsource InputSource = new InputSource (inPutstream); if (encodedresource.getencoding () = null) {inputsource.setencoding (encodedresource.getencoding ());}// The specific reading process can be found in the doloadbeandefinitions method int i = Doloadbeandefinitions (InputSource, Encodedresource.getresource ()); Inputstream.close (); Currentresources.remove (Encodedresource); if (Currentresources.isempty ()) This.resourcesCurrentlyBeingLoaded.remove (); return i; } finally {InputStream inputstream; Inputstream.close ();}} catch (IOException ex) {throw new Beandefinitionstoreexception ("IOException parsing XML document from" + ENCODEDRESOURC E.getresource (), ex); } finally {Currentresources.remove (encodedresource); if (Currentresources.isempty ()) This.resourcesCurrentlyBeingLoaded.remove (); } throw LocalObject2; }
Specific read process: Doloadbeandefinitions

protected int doloadbeandefinitions (InputSource inputsource, Resource Resource) throws Beandefinitionstoreexception { try {int validationmode = Getvalidationmodeforresource (Resource);//The Document object of the XML file is obtained here, this parsing process is done by Documentloader, This documentloader is Defaultdocumentloader, where documentloader is defined to create the Document doc = This.documentLoader.loadDocument ( InputSource, Getentityresolver (), This.errorhandler, Validationmode, Isnamespaceaware ()); This starts with the detailed process of parsing the beandefinition, which uses the spring bean configuration rules. Return Registerbeandefinitions (Doc, Resource); } catch (Beandefinitionstoreexception ex) {throw ex;} catch (Saxparseexception ex) {throw new Xmlbeandefinitionstoreexc Eption (Resource.getdescription (), "line" + ex.getlinenumber () + "in XML document from" + Resource + "is invalid", ex); } catch (Saxexception ex) {throw new Xmlbeandefinitionstoreexception (Resource.getdescription (), "XML document from" + R Esource + "is invalid", ex); } catch (Parserconfigurationexception ex) {throw new BeandefiniTionstoreexception (Resource.getdescription (), "Parser configuration exception parsing XML from" + Resource, ex);} catch (IOException ex) {throw new Beandefinitionstoreexception (Resource.getdescription (), "IOException parsing XML Document from "+ Resource, ex);} catch (Throwable ex) {} throw new Beandefinitionstoreexception (Resource.getdescription (), "unexpected exception parsing XML document from "+ Resource, ex);} Call this method public int registerbeandefinitions (Document doc, Resource Resource) throws Beandefinitionstoreexception { Beandefinitiondocumentreader Documentreader = Createbeandefinitiondocumentreader (); int countbefore = GetRegistry (). Getbeandefinitioncount (); Documentreader.registerbeandefinitions (Doc, Createreadercontext (Resource)); Return GetRegistry (). Getbeandefinitioncount ()-Countbefore; }


The parsing of the specific spring beandefinition is done in the beandefinitionparserdelegate. This class contains the processing of the various spring bean definition rules.

Let's take an example to analyze this process, such as how we are most familiar with how the bean element is handled, that is, how the most common element information that we have in the XML definition file is handled <bean></bean>. Here, we will see the familiar beandefinition definition of the processing, such as ID, name, aliase and other attribute elements. After the values of these elements are read from the attributes of the corresponding elements of the XML file, they are set to the generated Beandefinitionholder. The parsing of these properties is still relatively straightforward. For other element configuration parsing, such as the various bean attribute configuration, through a more complex parsing process, this process is done by parsebeandefinitionelement. After parsing is completed, the parsing results are placed in the Beandefinition object and set to Beandefinitionholder.

     public Beandefinitionholder parsebeandefinitionelement (Element ele, beandefinition Containingbean) {String id = ele.getattribute ("id"); String nameattr = Ele.getattribute ("name"); List aliases = new ArrayList (); if (Stringutils.haslength (nameattr)) {string[] Namearr = Stringutils.tokenizetostringarray (NameAttr, ",;"); Aliases.addall ((Collection) arrays.aslist (Namearr)); } String beanname = ID; if ((! Stringutils.hastext (Beanname)) && (!aliases.isempty ())) {Beanname = (String) aliases.remove (0); if ( This.logger.isDebugEnabled ()) {This.logger.debug ("No XML ' id ' specified-using '" + beanname + "' as Bean name and" + A Liases + "as aliases"); }} if (Containingbean = = null) {checknameuniqueness (beanname, aliases, ele)}//This method throws a detailed parsing of the bean element abstractbeandefinit Ion Beandefinition = Parsebeandefinitionelement (Ele, Beanname, Containingbean); if (beandefinition! = null) {if (! Stringutils.hastext (Beanname)) {try {if (Containingbean! = null) {Beanname= Beandefinitionreaderutils.generatebeanname (Beandefinition, This.readerContext.getRegistry (), true); } else {beanname = This.readerContext.generateBeanName (beandefinition); String beanclassname = Beandefinition.getbeanclassname (); if ((beanclassname! = null) && (Beanname.startswith (beanclassname)) && (Beanname.length () > Beanclassname.length ()) && (!this.readercontext.getregistry (). Isbeannameinuse (Beanclassname))) { Aliases.add (Beanclassname); }} if (This.logger.isDebugEnabled ()) This.logger.debug ("Neither XML ' id ' nor ' name ' specified-using generated bean name ["+ Beanname +"] ");} catch (Exception ex) {error (Ex.getmessage (), ele); return null;}} string[] Aliasesarray = Stringutils.tostringarray (aliases); return new Beandefinitionholder (Beandefinition, Beanname, Aliasesarray); } return null; }

After the specific build beandefinition. Let's give an example of the property parsing to complete the analysis of the entire beandefinition loading process, or in the class Beandefinitionparserdelegate code, It parses a layer of definitions in beandefinition, such as from a collection of attribute elements to a specific property element, and then to the specific property value. Based on the parsing results, the processing of these property values is encapsulated into a PropertyValue object and set to the Beandefinition object, as shown in the following code listing.

public void parsepropertyelements (element Beanele, beandefinition BD) {//traverse the property element defined under all bean elements NodeList nl = Beanele. Getchildnodes (); for (int i = 0; i < nl.getlength (); i++) {Node node = Nl.item (i); if ((Iscandidateelement (Node)) && (Nodenamee Quals (node, "property"))//After judging is the property element to enter Parsepropertyelement parsing parsepropertyelement (Element) node, BD); } }

Enter Parsepropertyelement parsing


public void Parsepropertyelement (Element ele, beandefinition BD) {//The name of the property is obtained here String propertyname = Ele.getattribu Te ("name"); if (! Stringutils.haslength (PropertyName) {error ("Tag ' property ' must has a ' name ' attribute", ele); return;} This.parsestat E.push (New Propertyentry (PropertyName)); try {//If the same bean already exists with the same name, it is not parsed and returned directly. That is, if you have a property setting with the same name in the same bean, it is only the first one that works. if (Bd.getpropertyvalues (). Contains (PropertyName)) {error ("multiple ' property ' definitions '" + PropertyName + "'", ele); Return }//This is where the property value is parsed, and the returned object corresponds to the parse result of the attribute setting of the bean definition, which is encapsulated in the PropertyValue object and then set to Beandefinitionholder Object val = parsepropertyvalue (Ele, BD, PropertyName); PropertyValue PV = new PropertyValue (PropertyName, Val); Parsemetaelements (Ele, PV); Pv.setsource (Extractsource (ele)); Bd.getpropertyvalues (). Addpropertyvalue (PV); } finally {This.parseState.pop ();} this.parseState.pop (); }

Parsepropertyvalue method specific code

  Public Object Parsepropertyvalue (Element ele, beandefinition BD, String propertyname) {String elementname = proper Tyname! = null? "<property> element for property '" + propertyname + "'": "<constructor-arg> element"; NodeList nl = ele.getchildnodes (); Element subelement = null; for (int i = 0; i < nl.getlength (); i++) {Node node = Nl.item (i); Node instanceof Element)) | | (Nodenameequals (node, "description")) | | (Nodenameequals (node, "meta"))) Continue if (subelement! = null) {error (ElementName + "must not contain more than one sub-element", ele);} else {subelement = ( Element) node; }} Boolean Hasrefattribute = Ele.hasattribute ("ref"); Boolean hasvalueattribute = Ele.hasattribute ("value"); The property's properties are judged here, ref or value, and are not allowed to be both ref and value. if (((Hasrefattribute) && (hasvalueattribute)) | | ((Hasrefattribute) | | (Hasvalueattribute)) && (subelement! = null))) {error (ElementName + "is only allowed to contain either ' ref ' attribute OR ' VALue ' attribute OR sub-element ', ele); }//If it is ref, create a ref data Object Runtimebeanreference, which encapsulates the information for ref. if (hasrefattribute) {String refName = Ele.getattribute ("ref"); Stringutils.hastext (refName)) {error (ElementName + "contains empty ' ref ' attribute", ele);} Runtimebeanreference ref = new Runtimebeanreference (refName); Ref.setsource (Extractsource (ele)); return ref; }//If it is value, create a data object of value Typedstringvalue, which encapsulates the information of value. if (hasvalueattribute) {Typedstringvalue Valueholder = new Typedstringvalue (Ele.getattribute ("value")); Valueholder.setsource (Extractsource (ele)); return valueholder; }//If there are child elements, the parsing of the child element is triggered if (subelement! = null) {return parsepropertysubelement (subelement, BD);} error (ElementName + "mu St Specify a ref or value ", ele); return null; }

After such a layer of parsing, the beandefinition we define in the XML file is loaded into the IOC container and the data map is established in the container. The corresponding data structure is established in the IOC container, or it can be seen as an image of the Pojo object in the IOC container, which can be used as an entry point for the IOC container to perform indexing, querying, and operation.

Reference: Spring Technology Insider-in-depth analysis of spring architecture and design principles, spring source code.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.