The @requestMapping annotation process in SpringMvc can be divided into the following 6 steps:

1. Registered RequestMappingHandlerMapping bean

In AnnotationDrivenBeanDefinitionParser type parse () method:

@Override
public BeanDefinition parse(Element element, ParserContext context) {
    Object source= context.extractSource(element); XmlReaderContext readerContext = context.getReaderContext(); / / generated RequestMappingHandlerMapping bean information RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class); handlerMappingDef.setSource(source);
    handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    handlerMappingDef.getPropertyValues().add("order", 0);
    handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); / / here HANDLER_MAPPING_BEAN_NAME value is: RequestMappingHandlerMapping the name of the class / / container registered name of RequestMappingHandlerMapping class names context.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME)); }Copy the code

You can see that the above method registers a bean named “HANDLER_MAPPING_BEAN_NAME” in the Spring MVC container.

2. Instantiate the RequestMappingHandlerMapping bean.

Enter the initHandlerMethods initialization method to view the logic:

protected void initHandlerMethods() {//1. Get the names of all beans in the container. / / according to detectHandlerMethodsInAncestorContexts bool variable values determine whether get bean in the parent container, by defaultfalse. So just get the beans from the Spring MVC container, Don't go to find the parent container String [] beanNames = (enclosing detectHandlerMethodsInAncestorContexts? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); // Loop over the beanfor(String beanName : beanNames) { //2. Determine whether the bean has an @Controller or @requestMappin annotationif(beanType ! = null && isHandler(beanType)) { //3. Process the bean with the annotation to get the handler function information. detectHandlerMethods(beanName); } } @Override protected boolean isHandler(Class<? > beanType) {return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
			AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
Copy the code

(1) Get the bean in the Spring MVC container. (2) Find beans with @Controller or @requestMappin annotations. (3) Parse the bean with annotations.

Check out the detectHandlerMethods () method.

protected void detectHandlerMethods(final Object handler) { //1. Get the bean's Class information Class<? > handlerType = (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()); final Class<? > userType = ClassUtils.getUserClass(handlerType); / / 2. Traversal functions have @ RequestMapping annotation function information Map < T > Method, the methods = MethodIntrospector. SelectMethods (userType, New MethodIntrospector. MetadataLookup < T > () {@ Override public T inspect Method (Method) {try {/ / if you have @ RequestMapping annotations, Gets function mapping informationreturngetMappingForMethod(method, userType); }}); //3. Iterate through the list of mapping functions and register handlerfor(Map.Entry<Method, T> entry : methods.entrySet()) { Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType); T mapping = entry.getValue(); // Register the handler function registerHandlerMethod(handler, invocableMethod, mapping); }} See how createRequestMappingInfo is implemented. protected RequestMappingInfo createRequestMappingInfo( RequestMapping requestMapping, RequestCondition<? > customCondition) {return RequestMappingInfo
         .paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
         .methods(requestMapping.method())
         .params(requestMapping.params())
         .headers(requestMapping.headers())
         .consumes(requestMapping.consumes())
         .produces(requestMapping.produces())
         .mappingName(requestMapping.name())
         .customCondition(customCondition)
         .options(this.config)
         .build();
}

Copy the code

You can see above that the RequestMapping annotation is returned after putting all the information in a RequestMappingInfo instance. After generating the function mapping information with the @requestMapping annotation, the last step is to call registerHandlerMethod to register the handler and handle the function mapping.

3. Get RequestMappingHandlerMapping the bean instance.

In the initHandlerMappings method:

Private void initHandlerMappings(ApplicationContext context) {// The name in the container is"ANDLER_MAPPING_BEAN_NAME"HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, handlerMapping.class); // Put the found beans in hanlderMappings. this.handlerMappings = Collections.singletonList(hm); }Copy the code

Enter the initHandlerMappings() method. Here we see a bean named “HANDLER_MAPPING_BEAN_NAME” from the container. This bean, as you may remember, is the HandlerMapping bean registered and instantiated earlier.

4. Receive the REqUST request.

5. To find the corresponding handler in the RequestMappingHandlerMapping instance.

6. Handler Processes the request.