- Research IOC first create a simple Web project, and we'll add a sentence to the XML.
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationcontext.xml</param-value> </context-param> <listener> < Listener-class>org.springframework.web.context.contextloaderlistener</listener-class> </ Listener>
This means that when the Web container starts, it enters the Contextloaderlistener class first, and then loads the Applicationcontext.xml file under Classpath. So the focus is on the Contextloaderlistener, point open Source code:
/** * Initialize The root Web application context. */ @Override public void contextinitialized (Servletcontextevent event) { Initwebapplicationcontext ( Event.getservletcontext ()); } /** * Close The root Web application context. */ @Override public void contextdestroyed (Servletcontextevent event) { Closewebapplicationcontext ( Event.getservletcontext ()); Contextcleanuplistener.cleanupattributes (Event.getservletcontext ()); }
The two implementations of the Servletcontextlistener interface are mainly used. The Web container first calls the Contextinitialized method, passes in the Tomcat encapsulated container resource, and then calls the parent class's initialization container method.
/*** The root Webapplicationcontext instance that this loader manages.*/private webapplicationcontext context;public WebA Pplicationcontext Initwebapplicationcontext (ServletContext servletcontext) {..... Omit//Store context in the local instance variable, to guarantee that//It's available on ServletContext shutdown. if (This.context = = null) {This.context = Createwebapplicationcontext (ServletContext); } if (This.context instanceof configurablewebapplicationcontext) {Configurablewebapplicati Oncontext CWAC = (configurablewebapplicationcontext) this.context; if (!cwac.isactive ()) {//the context has not yet been refreshed, provide services such as Setting the parent context, setting the application context ID, etc if (cwac.getparent ( ) = = null) {//The context instance is injected without an explicit PARent//Determine parent for root Web application context, if any. ApplicationContext parent = Loadparentcontext (ServletContext); Cwac.setparent (parent); } configureandrefreshwebapplicationcontext (CWAC, ServletContext); }} servletcontext.setattribute (Webapplicationcontext.root_web_application_context_attribute, THIS.C Ontext); ClassLoader CCL = Thread.CurrentThread (). Getcontextclassloader (); if (CCL = = ContextLoader.class.getClassLoader ()) {currentcontext = This.context; } else if (CCL! = null) {Currentcontextperthread.put (CCL, this.context); } ...... Omit return this.context; }
The main step of this method is the Createwebapplicationcontext method used to create the root container of Xmlwebapplicationcontext, which is taken from servletcontextevent.
The Loadparentcontext method is used to load the parent container. The Main method Configureandrefreshwebapplicationcontext is used to configure and refresh the root container, the most important thing in the method is the Refresh method, which implements the most important function.
@Override public void Refresh () throws Beansexception, IllegalStateException {synchronized (This.startupshutdow Nmonitor) {//Prepare this context for refreshing. Preparerefresh (); Tell the subclass to refresh the internal bean factory. Configurablelistablebeanfactory beanfactory = Obtainfreshbeanfactory (); Prepare The Bean factory for use with this context. Preparebeanfactory (beanfactory); try {//allows post-processing of the Bean factory in context subclasses. Postprocessbeanfactory (beanfactory); Invoke factory processors registered as beans in the context. Invokebeanfactorypostprocessors (beanfactory); Register Bean processors that intercept bean creation. Registerbeanpostprocessors (beanfactory); Initialize message source for this context. Initmessagesource (); Initialize Event Multicaster for this context. Initapplicationeventmulticaster (); Initialize other special beans in specific context subclasses. Onrefresh (); Check for listener beans and register them. Registerlisteners (); Instantiate all remaining (Non-lazy-init) singletons. Finishbeanfactoryinitialization (beanfactory); Last Step:publish corresponding event. Finishrefresh (); } catch (Beansexception ex) {Logger.warn ("Exception encountered during context initialization- Cancelling refresh attempt ", ex); Destroy already created singletons to avoid dangling resources. Destroybeans (); Reset ' active ' flag. CancelRefresh (ex); Propagate exception to caller. Throw ex; } } }
The Preparerefresh method is used to prepare the environment to be used later.
Obtainfreshbeanfactory method gets Beanfactory
@Override protected final void Refreshbeanfactory () throws Beansexception { if (hasbeanfactory ()) { Destroybeans (); Closebeanfactory (); } try { Defaultlistablebeanfactory beanfactory = Createbeanfactory (); Beanfactory.setserializationid (GetId ()); Customizebeanfactory (beanfactory); Loadbeandefinitions (beanfactory); Synchronized (this.beanfactorymonitor) { this.beanfactory = beanfactory; } } catch (IOException ex) { throw new applicationcontextexception ("I/O error parsing bean definition source for" + getd Isplayname (), ex); } }
The beanfactory that is actually returned is the implementation class defaultlistablebeanfactory, which instantiates the class that is used to instantiate the XML after it is loaded.
Loadbeandefinitions is an important method for really loading classes, and it's all about getting ready for work.
@Override protected void loadbeandefinitions (Defaultlistablebeanfactory beanfactory) throws Beansexception, IOException { //Create A new xmlbeandefinitionreader for the given beanfactory. Xmlbeandefinitionreader Beandefinitionreader = new Xmlbeandefinitionreader (beanfactory); Configure The bean definition reader with this context ' s //resource loading environment. Beandefinitionreader.setenvironment (Getenvironment ()); Beandefinitionreader.setresourceloader (this); Beandefinitionreader.setentityresolver (New Resourceentityresolver (this)); Allow a subclass to provide custom initialization of the reader, //Then proceed with actually loading the bean def Initions. Initbeandefinitionreader (Beandefinitionreader); Loadbeandefinitions (Beandefinitionreader); }
Overwrite this method in Xmlwebapplicationcontext, internally creating the Xmlbeandefinitionreader class, which is used as a read operator of the Bean in the XML, initializing the environment and loading the class
protected void Loadbeandefinitions (Xmlbeandefinitionreader reader) throws IOException { string[] configlocations = Getconfiglocations (); if (configlocations! = null) {for (String configlocation:configlocations) { reader.loadbeandefinitions ( configlocation);}}}
This configuration file is loaded with Xmlbeandefinitionreader after obtaining the configuration file information (for example: Classpath:applicationContext.xml) that was placed in the array prior to initialization.
The XML file information is then encoded and decoded:
/** * Load Bean definitions from the specified XML file. * @param resource The Resource descriptor for the XML file * @return The number of the bean definitions found * @throw s beandefinitionstoreexception in case of loading or parsing errors */ @Override public int Loadbeandefinitions (Resource Resource) throws Beandefinitionstoreexception { return loadbeandefinitions (new Encodedresource (Resource)); }
Key steps:
InputStream InputStream = Encodedresource.getresource (). getInputStream (); try { InputSource inputsource = new InputSource (inputstream); if (encodedresource.getencoding () = null) { inputsource.setencoding (encodedresource.getencoding ()); } Return Doloadbeandefinitions (InputSource, Encodedresource.getresource ()); } finally { inputstream.close (); }
After the formal load gets to the XML resource parsing
protected int doloadbeandefinitions (InputSource inputsource, Resource Resource) throws beandefinitionstoreexception { Document doc = doloaddocument (InputSource, Resource); Return Registerbeandefinitions (Doc, Resource); }
The main step is to parse the XML file into the document element with sax and register it in the Beandefinitions container.
The processing method of the Doloaddocument method and the way Sax handles XML documents are almost the same, so you can refer to the SAX parsing XML process
The process of parsing is many, such as
private void Parsedefaultelement (Element ele, beandefinitionparserdelegate delegate) { if ( Delegate.nodenameequals (Ele, import_element)) {//Parse IMPORT importbeandefinitionresource (ele); } else if (delegate.nodenameequals (Ele, alias_element)) {//Parse ALIAS processaliasregistration (ele); } else if (delegate.nodenameequals (Ele, bean_element)) {//Parse BEAN processbeandefinition (Ele, delegate); } else if (delegate.nodenameequals (Ele, nested_beans_element)) {//Parse BEANS //recurse Doregisterbeandefinitions (ele); } }
The individual labels are parsed and injected into the container.
Research on the IOC source code for spring Web launch