Start with a simple example:
Scene class Client.java
Package Com.dusk.bean;
Import Org.junit.Test;
Import org.springframework.beans.factory.BeanFactory;
Import org.springframework.beans.factory.xml.XmlBeanFactory;
Import Org.springframework.core.io.ClassPathResource;
Import Org.springframework.core.io.Resource;
public class Client {
@Test public
void Test () {
Resource resource=new classpathresource ("com/dusk/bean/ Bean.xml ");
Beanfactory beanfactory=new xmlbeanfactory (Resource);
Hello Hello=beanfactory.getbean (hello.class);
Hello.sayhello ();
}
}
Bean entity class Hello.java
Package Com.dusk.bean;
public class Hello {
private String name;
public void SetName (String name) {
this.name = name;
}
public void SayHello () {
System.out.println ("Hello," +name+ "!");
}
}
Configuration file Bean.xml
<?xml version= "1.0" encoding= "UTF-8"?> <beans
xmlns= "Http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop= "http://www.springframework.org/ SCHEMA/AOP "
xsi:schemalocation=" Http://www.springframework.org/schema/aop http://www.springframework.org/ Schema/aop/spring-aop.xsd
Http://www.springframework.org/schema/beans Http://www.springframework.org/schema /beans/spring-beans.xsd ">
<bean id=" Hello "class=" Com.dusk.bean.Hello ">
<property name=" name " value= "Dusk"/>
</bean>
</beans>
Of course, the output is:
Hello, dusk!.
Next, let's look at the loading process for XML configuration.
1. Classpathresource is used to point to a resource under a classpath, where com/dusk/bean/bean.xml represents an XML file that contains the spring bean configuration.
public class Xmlbeanfactory extends Defaultlistablebeanfactory {private final
Xmlbeandefinitionreader reader = new Xmlbeandefinitionreader (this);
/** * Create A new xmlbeanfactory with the given resource, * which must is parsable using DOM. * @param resource XML resource to load beans definitions from * @throws beansexception in case of loading or parsing Erro
RS */Public xmlbeanfactory (Resource Resource) throws Beansexception {This (Resource, null);
}/** * Create a new xmlbeanfactory with the given input stream, * which must is parsable using DOM. * @param resource XML resource to load beans definitions from * @param parentbeanfactory parent Bean Factory * @throws Beansexception in case of loading or parsing errors */public xmlbeanfactory (Resource Resource, Beanfactory parentbeanf
Actory) throws Beansexception {super (parentbeanfactory); <strong>this.reader.loadbeandefinitions (Resource);</strong>}}
The bold code above allows you to know that the configuration file is loaded by Xmlbeandefinitionreader. First, the XML configuration file for spring is handled by sax. Refer to the blog for sax
Sax detailed.
Draw a simple sequence diagram, the use of sequence diagram is welcome to correct.
We can see from the diagram that parsing XML is done primarily by the Org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader class, which is the default parsing class provided by spring, and of course you can customize Their own resolution.
It can be seen that spring provides a good enhancement mechanism for you to enhance this class, with two empty methods reserved for developers.
/**
* Parse custom element where
* <p>allow the XML to is extensible by processing any custom element types first,
* BEF Ore we start to process the bean definitions. This method was a natural * extension point for any and other
custom pre-processing of the XML.
* <p>the default implementation is empty. Subclasses can override this method
to * Convert custom elements into standard Spring beans definitions, for example.
* Implementors has access to the parser ' s bean definition Reader
and the * underlying XML resource, through the CO Rresponding accessors.
* @see #getReaderContext ()
*/
protected void Preprocessxml (Element root) {
}
And
/**
* Allow the XML to being extensible by processing a custom element types last,
* after we finished processing T He bean definitions. This method was a natural * extension point for any and other
custom post-processing of the XML.
* <p>the default implementation is empty. Subclasses can override this method
to * Convert custom elements into standard Spring beans definitions, for example.
* Implementors has access to the parser ' s bean definition Reader
and the * underlying XML resource, through the CO Rresponding accessors.
* @see #getReaderContext ()
*/
protected void Postprocessxml (Element root) {
}
Both of these methods are protected, in order to facilitate the subclass rewrite, and both are empty methods.
The main parsing XML method is Parsebeandefinitions, as follows:
/**
* Parse The elements at the root level in the document:
* "Import", "Alias", "Bean".
* @param root the DOM root element
of the document *
/protected void parsebeandefinitions (element root, Beandefini Tionparserdelegate delegate) {
if (delegate.isdefaultnamespace (root)) {
NodeList nl = root.getchildnodes ();
for (int i = 0; i < nl.getlength (); i++) {
node node = nl.item (i);
if (node instanceof element) {
element ele = (element) node;
if (Delegate.isdefaultnamespace (ele)) {
parsedefaultelement (ele, delegate);
}
else {
delegate.parsecustomelement (ele);
}}}} else {
delegate.parsecustomelement (root);
}
}
It can be seen that it is loop-processed, and then read the detailed content:
/* Parsing process, analysis of the default elements for example, Bean
*
/private void Parsedefaultelement (element ele, Beandefinitionparserdelegate delegate) {
if (delegate.nodenameequals (Ele, import_element)) {
//import element
Importbeandefinitionresource (ele);
}
else if (delegate.nodenameequals (Ele, alias_element)) {
//alias element
processaliasregistration (ele);
}
else if (delegate.nodenameequals (Ele, bean_element)) {
//bean element
processbeandefinition (Ele, delegate);
}
Else if (delegate.nodenameequals (Ele, nested_beans_element)) {
//beans element
//Recurse (Recursive)
Doregisterbeandefinitions (ele);
}
}
And
/** * Parse an ' import ' element and load the bean definitions * from the given resource into the Bean factory.
*/protected void Importbeandefinitionresource (Element ele) {String location = Ele.getattribute (Resource_attribute); if (!
Stringutils.hastext (location)) {Getreadercontext (). Error ("Resource location must not being empty", ele);
Return }//Resolve system properties:e.g. "${user.dir}" location = Getreadercontext (). Getenvironment (). Resolverequiredplac
Eholders (location);
set<resource> actualresources = new linkedhashset<resource> (4);
Discover whether the location was an absolute or relative URI Boolean absolutelocation = false; try {absolutelocation = Resourcepatternutils.isurl (location) | |
Resourceutils.touri (location). Isabsolute (); } catch (URISyntaxException ex) {//cannot convert to a URI, considering the location relative//unless it is t He well-known Spring prefix "classpath*:"}//Absolute or relAtive? if (absolutelocation) {try {int importcount = Getreadercontext (). Getreader (). loadbeandefinitions (Location, actual
Resources); if (logger.isdebugenabled ()) {Logger.debug ("imported" + importcount + "Bean definitions from URL location [" + Loc
ation + "]"); }} catch (Beandefinitionstoreexception ex) {Getreadercontext (). Error ("Failed to import bean definitions
From URL location ["+ Location +"] ", Ele, ex);
}} else {//No URL--considering resource location as relative to the current file.
try {int importcount;
Resource Relativeresource = Getreadercontext (). GetResource (). createrelative (location); if (relativeresource.exists ()) {Importcount = Getreadercontext (). Getreader (). Loadbeandefinitions (RelativeResource)
;
Actualresources.add (Relativeresource);
} else {String baselocation = Getreadercontext (). GetResource (). GetURL (). toString (); Importcount = Getreadercontext (). Getreader (). LoAdbeandefinitions (Stringutils.applyrelativepath (baselocation, location), actualresources); } if (logger.isdebugenabled ()) {Logger.debug ("imported" + importcount + "Bean definitions from relative Locati
On ["+ Location +"] ");
}} catch (IOException ex) {Getreadercontext (). Error ("Failed to resolve current resource location", Ele, ex); } catch (Beandefinitionstoreexception ex) {Getreadercontext (). Error ("Failed to import beans definitions from RelA
tive location ["+ Location +"] ", Ele, ex);
}} resource[] Actresarray = Actualresources.toarray (New resource[actualresources.size ());
Getreadercontext (). fireimportprocessed (location, Actresarray, Extractsource (ele));
}/** * Process the given alias element, registering the alias with the registry.
*/protected void processaliasregistration (Element ele) {String name = Ele.getattribute (Name_attribute);
String alias = Ele.getattribute (Alias_attribute); Boolean valid = True if (!
Stringutils.hastext (name)) {Getreadercontext (). Error ("Name must not is empty", ele);
valid = false; } if (!
Stringutils.hastext (alias)) {Getreadercontext (). Error ("Alias must Not is empty", ele);
valid = false;
} if (valid) {try {getreadercontext (). GetRegistry (). Registeralias (name, alias); } catch (Exception ex) {Getreadercontext (). Error ("Failed to register alias '" + Alias + "' for Beans with Nam
E ' "+ Name +" ' ", Ele, ex);
} getreadercontext (). firealiasregistered (name, alias, Extractsource (Ele));
}
}
/**
* Process The given bean element, parsing the bean definition
* and registering it with the registry.
*
/protected void processbeandefinition (Element ele, beandefinitionparserdelegate delegate) {
Beandefinitionholder Bdholder = delegate.parsebeandefinitionelement (ele);
if (Bdholder! = null) {
Bdholder = delegate.decoratebeandefinitionifrequired (Ele, bdholder);
try {
//registers the bean definition//register as Beanfactory in the
final decorated instance.
Beandefinitionreaderutils.registerbeandefinition (Bdholder, Getreadercontext (). GetRegistry ());
}
catch (Beandefinitionstoreexception ex) {
getreadercontext (). Error ("Failed to register bean definition with Name '" +
Bdholder.getbeanname () + "'", Ele, ex);
}
<strong>//sends an event to the IOC container, representing parsing and registration completion
//Send registration event.
Getreadercontext (). firecomponentregistered (New Beancomponentdefinition (Bdholder));</strong>
}
}
The above is the spring default parsing XML step.
He who wants to be a man will suffer before his ancestors.