Spring Version: 4.0.X
Note: The analysis here focuses only on the approximate process of the entire process and omits the process-independent code.
Application of root context (root ApplicationContext) startup
We know that when using SPRINGMVC in a Web project, you need to web.xml configure a listener in:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
So ContextLoaderListener that is the entry point for our analysis. The inheritance structure of this class is as follows:
In this class we find a private WebApplicationContext context declaration that the class actually holds the container object, which is indicated by the annotations in spring that this is the root context of the entire application. So WebApplicationContext which is the specific implementation class and where is it instantiated?
When the deployment is applied to the application server, the application server first invokes the listener's contextInitialized() method, so we go to ContextLoaderListener the contextInitialized() method and see that there is only one row called, namely:
initWebApplicationContext(event.getServletContext());
This method is implemented in its parent class ContextLoader . Entering this method, it is found that the following code is called:
try {if (This.context = = null) {This.context = Createwebapplicationcontext (ServletContext); }// ... ... Servletcontext.setattribute (Webapplicationcontext.root_web_application_context_attribute, This.context); ... ... return this.context; } catch (RuntimeException ex) {// ... }
It is visible that the createWebApplicationContext() method is responsible for creating the container, and when created, Spring puts the reference to the root container ServletContext in order for subsequent reads to be used. The WebApplicationContext definitions that you can see in the interface ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE are as follows:
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class".ROOT";
That is, the fully qualified name of the class plus. Root suffix.
Let's go deep into the createWebApplicationContext() method, the code is roughly the following:
...... return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
It is known that spring creates a container class by reflection (nonsense). In the determineContextClass() method, spring first looks at whether the user web.xml has specified a custom container class in, and, if there is one, Class.forName() gets the class object of the classes, and if not specified, uses the default container class, which is WebXmlApplicationContext implemented.
This completes the creation of the root context for the entire Web application.
Dispatcherservlet the start of a child container
Before analyzing the process, first look at the inheritance structure of the class:
Spring has used a lot of template patterns in the design implementation of Dispatcherservlet, so many times it is not possible to see what the sub-class is looking for, and the complete processing logic is mostly defined in its parent class, and subclasses simply rewrite some of the template methods of the parent class.
When the root context is created, Spring creates a container for each dispatcherservlet, whose references are stored in its immediate parent class FrameworkServlet :
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { ...... private WebApplicationContext webApplicationContext; ......}
This container is a child container of the root container.
We know that a servlet container, such as Tomcat, will first call the Init () method to initialize the servlet when creating a servlet, so you should first look for the method.
After finding the analysis, we found that the creation of the container HttpServletBean was triggered by the method of the parent class init() , and the FrameworkServlet actual creation work was done by the subclass.
HttpServletBean#init()The approximate structure of the method is as follows:
// Set bean properties from init parameters. try { } catch (BeansException ex) { ...... } // 这是一个模板方法,由子类实现 initServletBean();
The try-catch code for the container is not created in the statement, but we see that the method is called later initServletBean() . But HttpServletBean the initServletBean() method is just an empty implementation, so we're going to look at it in its subclasses FrameworkServlet#initServletBean() :
getServletContext().log("Initializing Spring FrameworkServlet ‘""‘"); long startTime = System.currentTimeMillis(); try { this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); } catch (ServletException ex) { ...... }
Finally, the word Initxxxcontext appears-the initWebApplicationContext() method first gets from the ServletContext ContextLoaderListener root container object reference that was completed by the initialization and put into it (because the child container must be passed in as a parameter), and then after the layer call, and finally createWebApplicationContext() , the main code for this method is as follows:
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) { Class<?> contextClass = getContextClass(); ...... // 通过工具类创建容器对象 ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setEnvironment(getEnvironment()); wac.setParent(parent); wac.setConfigLocation(getContextConfigLocation()); configureAndRefreshWebApplicationContext(wac); return wac; }
If you want to know exactly what type of container you are creating, you can continue to track the methods in the first row getContextClass() , and you can eventually find out XmlWebApplicationContext .
Dispatcherservlet Request Processing Process
When a child container is created, the Dispatcherservlet is ready for distribution when a request arrives. We first find the method based on the servlet specification, which is doService() DispatcherServlet implemented in its own way:
@Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { ...... try { doDispatch(request, response); } finally { ...... }
We omitted the irrelevant code, so we can see clearly that doDispatch() is the main implementation of the distribution request:
protected void Dodispatch (HttpServletRequest request, httpservletresponse response) throws Exception {Httpservletr Equest processedrequest = Request; Handlerexecutionchain mappedhandler = null; Boolean multipartrequestparsed = false; Webasyncmanager Asyncmanager = Webasyncutils.getasyncmanager (request);Try{Modelandview mv = null; Exception dispatchexception = null;Try{//Search is a file upload request Processedrequest = Checkmultipart (request); multipartrequestparsed = (processedrequest! = Request); Find handler Mappedhandler = GetHandler (processedrequest) capable of handling the current request;if(Mappedhandler = = NULL | | Mappedhandler.gethandler () = = null) {Nohandlerfound (processedrequest, response);return; }//Find the handler Adapter handleradapter ha = Gethandleradapter that can handle the current request (Mappedhandler.gethandl ER ()); //... ...The Prehandle () method of the interceptor is called here//visible, if the Prehandle () method returns false, terminates the distribution process and returns directlyif(!mappedhandler.applyprehandle (processedrequest, response)) {return; }Try{//This line is the real call to the Controller method we wrote MV = Ha.handle (processedrequest, Response, Mappedhan Dler.gethandler ()); } finally {if(Asyncmanager.isconcurrenthandlingstarted ()) {return; }} applydefaultviewname (request, MV); The Posthandle () method of the interceptor is called here, that is, after the controller call is complete mappedhandler.applyposthandle (processedrequest, Response, MV); } catch (Exception ex) {dispatchexception = ex; } processdispatchresult (Processedrequest, Response, Mappedhandler, MV, dispatchexception); } catch (Exception ex) {//... ...} finally {//... ...} }
Analysis here, Dispatcherservlet's distribution request processing process is at a glance.
Spring Source Analysis: SPRINGMVC START process and Dispatcherservlet request processing process