Article directory
Principle Analysis of SpringMVC Components
Mainly analyze the process of DispatcherServlet (front controller) initialization, and DispatcherServlet executes the main process
1. Front-end controller initialization
DispatcherServlet initialization does two things
- Obtained a SpringMVC ApplicationContext container
- Registered nine components of SpringMVC
1.1 Initialize the SpringMVC container
The front controller DispatcherServlet is the entrance of SpringMVC and the brain of SpringMVC, where the work of the main process is completed
DispatcherServlet is essentially a Servlet. When load-on-startup is configured, the creation and initialization init method will be executed when the server starts, and the service method will be executed for each request.
Look for the init method, and find that there is no DispatcherServlet class, so go to his father, FrameworkServlet class, and there is no father, so keep looking until there is an init method in the HttpServletBean class
Find the init method, see that an initServletBean method is called, click to see
The initServletBean method is as follows, and there is nothing found, indicating that it is implemented by a subclass, that is, the FrameworkServlet class
Find the initServletBean method in the FrameworkServlet class, and then find the following statement to get the Spring container in the web environment
Click to have a look and find that a Spring container has been created
Still in this method, look down and put the reference of the Spring container as a parameter in the following method
What is the effect of passing in the Spring container?
Set the reference of the Spring container as a property of SpringMVC, through this place to reflect the relationship of a parent-child container
What does the parent-child container do?
When SpringMVC acquires Bean, it will first obtain it from its own container. If it does not have its own container, it will use parent to find the parent container, which is the Spring container, and then check whether there is a corresponding Bean from inside.
Can Spring get the Bean in SpringMVC?
No, because SpringMVC is a sub-container
1.2 Registered nine components of SpringMVC
Not too often understand 141-SpringMVC Framework-Component Principle Analysis-Front Controller Initialization-Registration of Nine Major Components_哔哩哔哩_bilibili
When we create the SpringMVC container, we will execute the statement marked in red below
configureAndRefreshWebApplicationContext, configure and refresh the SpringMVC container
Go ahead and create if not
Click the method in the above picture, and click until the picture below
Found that there is also a call to the configureAndRefreshWebApplicationContext method
After the above two processes, whether it is a newly created SpringMVC container or only an existing SpringMVC container, the configureAndRefreshWebApplicationContext method will be executed
Click into the method configureAndRefreshWebApplicationContext
Found that there is a refresh method in this method
Click into the refresh method and find that a finishRefresh method is finally called to complete the refresh
Click into the finishRefresh method to have a look, an event is published in this method
We set this event, and the listeners corresponding to the event will be executed.
Go back to the FrameworkServlet class at this point
Find the following method, which is a listener. The listener is the generic ContextRefreshedEvent, which is the type of event we publish (above)
This FrameworkServlet.this.onApplicationEvent(event); code will execute
Why is it enforced?
在另一个地方会发布事件
Among them, there is a listener in the FrameworkServlet class that listens to the above events
After listening to this FrameworkServlet.this.onApplicationEvent(event); the code will be executed
Look at the onApplicationEvent method , there is an onRefresh method inside,
Look at the onRefresh method , but nothing is written inside, indicating that it is implemented by subclasses
Look at the onRefresh method in the DispatcherServlet class, a subclass of the FrameworkServlet class
Finally, register the nine components of SpringMVC
1.3 Processor mapper initialization details
Registered nine components, we can choose a familiar initHandlerMappings to view
The operation of this step is to see if there is a component of type HandlerMapping in the Spring container. If so, the matchingBeans parameter is not empty.
Then you can't enter the following if judgment at this time, and the components in the default configuration file will not be loaded
After the break point, why are there four parameters of the HandlerMapping type?
We previously configured an annotation @EnableWebMVC
Or in the spring-mvc.xml file
There are many functions of MVC annotation driver, which will help us inject some components into SpringMVC, where HandlerMapping is registered
The operations of the above sentences are all done by @EnableWebMVC annotation for us
If we comment out the @EnableWebMVC annotation, the size of the matchingBeans parameter is 0, and the components in the default configuration file will eventually be loaded, which is framed in the following figure
Four HandlerMapping type components, let's click to see one
But we only manually configured one interceptor, why are two shown?
Spring itself provides two
Look at the MappingRegistery parameter again
Just click in and have a look
2. The front-end controller executes the main process
When the server starts, DispatcherServlet will perform the initialization operation. Next, each visit will execute the service method . Let's take a macro look at the execution process and study the source code and component execution details.
2.1 Locating the doDispatcher method
Find the service method in the DispatcherServlet class, but there is no one, then find his father FrameworkServlet class, and find that there is a Service method, but this method is not the most original method, the most original method is the ServletRequest parameter
Look for the HttpServletBean class of the FrameworkServlet class, but there is no Service method
Look for the HttpServlet class again, and find that there is a Service method, and it is native (there is no http in front of the parameter)
The service method in the above figure calls the following service method (this service is overloaded)
Internally, according to the request method, see whether to call dopost or doGet
We can look at the doPost method, but there is a small sign on the left of this method, indicating that it has been overridden by a subclass
Click the small sign, then enter the FrameworkServlet class, and see the doPost method
A processRequest method is called in the doPost method
The doService method is called in the processRequest method, but we found that doService is an abstract method, we need to find the corresponding implementation
Take a look at the specific implementation of the doService abstract method, and you will arrive at the DispatcherServlet class
Another method doDispatch is called in the doService method
Take a look at the doDispatch method, the core main process is here
2.2 Verify HandlerExecutionChain
Start looking for doDispatch in the DispatcherServlet class
There is a parameter HandlerExecutionChain in this method, which includes Interceptor, target object
The call of this.getHandler(processedRequest) in this method initializes the parameter mappedHandler of HandlerExecutionChain
Let's take a look at what the getHandler method is, as shown below
If the parameter handlerMappings is not empty, loop it
What is the handlerMappings parameter? Click to see
Discovery is the final collection of HandlerMapping
The filling of HandlerMapping is explained in the previous 1.3
Go back to the getHandler method, where the mapping.getHandler(request) method is called when traversing the collection
Let's take a look at what the mapping.getHandler method does
Find the corresponding implementation, choose the first one
Then the corresponding implementation in this class calls the getHandlerExecutionChain method
Look at the getHandlerExecutionChain method again
Finally, the chain parameter is returned to the doDispatcher method, as marked in red below
The above process is the place marked in red in the figure below
2.3 HandlerAdapter executes the target method
The doDispatcher method has not been completed, continue to look down
Going down will call the getHandlerAdapter method
Continuing to go down, the preHandle pre-method of the interceptor will be executed
execute target method
execute post method
Then we found that the HandlerAdapter object was not executed when the pre-method and post-method were executed
But when the target method is executed, it is executed by the HandlerAdapter object
Then we can look at the handle method and execute the target method
Found that it is not implemented, let's look at the implementation of the subclass
Select the first one in the image below
Go down the screenshot
Finally arrived at the following place
Continue to execute, and you will enter the method marked in red below
continue to click in
At the following place, look at the parameters
The parameters in the above figure are the corresponding parameters when we visit
Then click into the doInvoke method
Then I found the method of executing method.invoke(this.getBean(), args)
Reflect code, and finally execute the target method through reflection