Spring IOC beandefinition Parsing
The IOC (inversion of Control), which controls inversion, is to say that control over the creation of objects is transferred, the initiative of creating objects previously and the timing of creation are controlled by themselves, and now this right is transferred to the Spring IOC container. Many extraordinary applications are implemented by two or more classes that implement business logic through each other's cooperative dependencies, and in Spring these dependencies can be managed by giving the object's dependency injection to the IOC container, which improves the testability of the code while decoupling the code.
1. load bean
the process of loading the bean:
(1) encapsulates the resource file. When entering Xmlbeandefinitionreader, the parameter resource is first encapsulated with the Encodedresource class.
(2) Gets the input stream. get the corresponding inputstream from the resource and construct the InputSource.
(3) continue calling function Doloadbeandefinitions through the constructed InputSource instance and resource instance .
Let's take a look at the specific implementation of the Doloadbeandefinitions function (a step in the middle that omits the Loadbeandefinitions specific method):
Public int loadbeandefinitions (Resource Resource) throws beandefinitionstoreexception { return Loadbeandefinitions (new Encodedresource (Resource));}
Continue to follow the code into the Real core processing Section doloadbeandefinitions (inputsource, encodedresource. getresource ())
protected int doloadbeandefinitions (InputSource inputsource, Resource Resource) throws Beandefinitionstoreexception { Try { = doloaddocument (inputsource, Resource); return registerbeandefinitions (Doc, Resource); } Catch (Beandefinitionstoreexception ex) { throw ex; } // ... Omit exception handling section }
In the lengthy code above, if you do not consider the code of the exception class, in fact, only do three things, the three things are necessary.
(1) Gets The validation mode for the XML file.
(2) Load the XML file and get the corresponding document.
(3) Register bean information According to the returned document .
2. get The validation mode for XML
protected Document doloaddocument (InputSource inputsource, Resource Resource) throws Exception { return This This . ErrorHandler, Getvalidationmodeforresource (Resource), Isnamespaceaware ()); }
2.1 Reading of the authentication mode
Readers of the XML file should know that the XML file's validation pattern guarantees the correctness of the XML file, and that there are two common validation patterns:DTD and XSD.
For validation mode, readers can view the data themselves.
The Read method for the validation mode is as follows:
protected intGetvalidationmodeforresource (Resource Resource) {intValidationmodetouse =Getvalidationmode (); if(Validationmodetouse! =Validation_auto) { returnValidationmodetouse; } intDetectedmode =Detectvalidationmode (Resource); if(Detectedmode! =Validation_auto) { returnDetectedmode; } //Hmm, we didn ' t get a clear indication ... Let ' s assume XSD,//since apparently no DTD declaration have been found up until//Detection stopped (before finding the document ' s root tag). returnvalidation_xsd; }
The implementation of the method is still very simple, nothing more than if the authentication mode is set to use the set of authentication mode, or use automatic authentication mode, self-detection verification mode of the function is relatively simple, here is no longer said.
3. get Document
After the verification mode is ready for the document to load, the same Xmlbeandefinitionreader for the reading of the documents are not pro-Pro, but entrusted to the Documentloader to execute, The parsing code is as follows (in Defaultdocumentloader)
PublicDocument loaddocument (InputSource inputsource, Entityresolver entityresolver, ErrorHandler ErrorHandler, /c10>intValidationmode, Boolean namespaceaware) throws Exception {Documentbuilderfactory Factory=createdocumentbuilderfactory (Validationmode, Namespaceaware); if(logger.isdebugenabled ()) {Logger.debug ("Using JAXP Provider ["+ Factory.getclass (). GetName () +"]"); } Documentbuilder Builder=Createdocumentbuilder (Factory, Entityresolver, ErrorHandler); returnBuilder.parse (InputSource); }
There is really not much to describe in this part of the code, because parsing XML documents through sax is roughly the same routine, andspring is nothing special here, but also first creating Documentbuilderfactory then creates the Documentbuilder through Documentbuilderfactory and then parses the InputSource to return the Document object.
4. Analysis and registration beandefinitions
After converting the file to document , the bean can then be extracted and registered .
Public intregisterbeandefinitions (Document doc, Resource Resource) throws Beandefinitionstoreexception {//instantiating Beandefinitiondocumentreader using DefaultbeandefinitiondocumentreaderBeandefinitiondocumentreader Documentreader =Createbeandefinitiondocumentreader ();//when instantiating Beandefinitionreader, the Beandefinitionregistry is passed in, using subclasses that inherit from Defaultlistablebeanfactory by default//number of beandefinition before logging statistics intCountbefore =getregistry (). Getbeandefinitioncount (); //loading and registering beansdocumentreader.registerbeandefinitions (Doc, Createreadercontext (Resource)); //record the number of beandefinition for this load returnGetRegistry (). Getbeandefinitioncount ()-Countbefore; }
Registerbeandefinitions method for entering Defaultbeandefinitiondocumentreader
Public void registerbeandefinitions (Document doc, Xmlreadercontext readercontext) { this. Readercontext = Readercontext; Logger.debug ("Loading Bean definitions"); = doc.getdocumentelement (); Doregisterbeandefinitions (root); }
Below the bottom doregisterbeandefinitions (root) method to enter the core logic
protected voiddoregisterbeandefinitions (Element root) {//Specialized Processing parsingBeandefinitionparserdelegate parent = This.Delegate; This.Delegate=createdelegate (Getreadercontext (), root, parent); if( This.Delegate. Isdefaultnamespace (Root)) { //working with the profile propertyString Profilespec =Root.getattribute (Profile_attribute); if(Stringutils.hastext (Profilespec)) {string[] specifiedprofiles=Stringutils.tokenizetostringarray (Profilespec, Beandefinitionparserdelegate.multi_value_attrib Ute_delimiters); if(!Getreadercontext (). Getenvironment (). Acceptsprofiles (Specifiedprofiles)) { if(logger.isinfoenabled ()) {Logger.info ("skipped XML bean definition file due to specified profiles ["+ Profilespec +"] not matching:"+Getreadercontext (). GetResource ()); } return; } } } //parsing pre-processing, leaving subclass implementationsPreprocessxml (root); Parsebeandefinitions (Root, This.Delegate); //Parse post-processing, left to subclass implementationPostprocessxml (root); This.Delegate=parent; }
use of 4.1profile properties
This feature allows you to deploy two sets of configurations in the configuration file for both production and development environments, which makes it easy to switch between development and deployment environments, with the most common being to replace different databases.
4.2 Parsing and registering beandefinitions
After the profile is processed, the XML can be read, and the tracking code enters parsebeandefinitions (root, this.delegate) .
protected voidParsebeandefinitions (Element root, beandefinitionparserdelegateDelegate) { //The treatment of beans if(Delegate. Isdefaultnamespace (Root)) {NodeList NL=root.getchildnodes (); for(inti =0; I < nl.getlength (); i++) {node node=Nl.item (i); if(node instanceof Element) {element Ele=(Element) node; if(Delegate. Isdefaultnamespace (Ele)) { //processing of the beanParsedefaultelement (Ele,Delegate); } Else { //processing of the bean Delegate. Parsecustomelement (Ele); } } } } Else { Delegate. Parsecustomelement (root); } }
The above code seems to be quite logical, because there are two major types of bean declarations in the XML configuration of spring, one is the default, one is custom, and the reading and parsing differences between the two methods are very large, if the spring default configuration is used ,Spring certainly knows what to do, but if it's a custom, it takes a long time for the user to implement some interface and configuration.
For label parsing, see my next article.
Spring IOC beandefinition Parsing