Interpretation of Spring MVC - <mvc:annotation-driven/>

Interpretation of Spring MVC - <mvc:annotation-driven/>

一、AnnotationDrivenBeanDefinitionParser

    Usually, if we want to develop Spring MVC through annotation, we will add the <mvc:annotation-driven/> tag to ***-servlet.xml to tell Spring our purpose. But why do we do this? What does this label mean? What does it do?

    Also to figure out these issues, like the <context:component-scan/> tag, we first find its parsing class. As mentioned in the first article, tag parsing under all custom namespaces (like mvc, context, etc.) is done by subclasses of the BeanDefinitionParser interface. See the pictures in the first article

We see that there are multiple AnnotationDrivenBeanDefinitionParser, they are used to deal with <annotation-driven/> tags in different namespaces, we are studying the <mvc:annotation-driven/> tag today, so we find the corresponding implementation class is org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser.
    By reading the class annotation document, we found that this class is mainly used to register with the factory

  • RequestMappingHandlerMapping

  • BeanNameUrlHandlerMapping

  • RequestMappingHandlerAdapter

  • HttpRequestHandlerAdapter

  • SimpleControllerHandlerAdapter

  • ExceptionHandlerExceptionResolver

  • ResponseStatusExceptionResolver

  • DefaultHandlerExceptionResolver 

    Several Bean instances above. What are these classes used for?

    The first two are the implementation classes of the HandlerMapping interface, which are used to process request mapping. The first of these deals with the @RequestMapping annotation. The second will map the name of the controller class to the request url.

    The middle three are used to handle requests. Specifically, it is to determine which method of which controller is called to process the current request. The first processor to handle @Controller annotations, supports custom method parameters and return values ​​(cool). The second is to handle handlers that inherit HttpRequestHandler. The third handles handlers that inherit from the Controller interface.

    The last three are parsers used to handle exceptions.

2. Realization

    Just saying that there is no evidence, let's look directly at the code:

public BeanDefinition parse(Element element, ParserContext parserContext) {
        Object source = parserContext.extractSource(element);

        CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
        parserContext.pushContainingComponent(compDefinition);

        RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);
        //第一个在这 RequestMappingHandlerMapping
        RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
        handlerMappingDef.setSource(source);
        handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        handlerMappingDef.getPropertyValues().add("order"0);
        handlerMappingDef.getPropertyValues().add("removeSemicolonContent"false);
        handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
        String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
        //第二个在这 RequestMappingHandlerAdapter
        RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
        handlerAdapterDef.setSource(source);
        handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
        handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
        handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
        if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
            Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));
            handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
        }
        if (argumentResolvers != null) {
            handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
        }
        if (returnValueHandlers != null) {
            handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
        }
        if (asyncTimeout != null) {
            handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
        }
        if (asyncExecutor != null) {
            handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
        }
        handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
        handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
        String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);
        //异常处理解析器
        RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
        exceptionHandlerExceptionResolver.setSource(source);
        exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
        exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
        exceptionHandlerExceptionResolver.getPropertyValues().add("order"0);
        String methodExceptionResolverName =
                parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);
        //异常处理解析器
        RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
        responseStatusExceptionResolver.setSource(source);
        responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        responseStatusExceptionResolver.getPropertyValues().add("order"1);
        String responseStatusExceptionResolverName =
                parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);
        //异常处理解析器
        RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
        defaultExceptionResolver.setSource(source);
        defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        defaultExceptionResolver.getPropertyValues().add("order"2);
        String defaultExceptionResolverName =
                parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);

        parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));
        parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
        parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
        parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
        parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
        parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
        //这里注册了BeanNameUrlHandlerMapping,SimpleControllerHandlerAdapter等
        // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
        MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

        parserContext.popAndRegisterContainingComponent();

        return null;
    }
//在这啊。
public static void registerDefaultComponents(ParserContext parserContext, Object source) {
        registerBeanNameUrlHandlerMapping(parserContext, source);
        registerHttpRequestHandlerAdapter(parserContext, source);
        registerSimpleControllerHandlerAdapter(parserContext, source);
    }

 

    Slightly long, but easy to read code. Looking at the comments, we found that it does register the classes mentioned above.

3. Summary

    We know that they automatically register so many beans for us, so what do these beans do?

    We mainly describe two of them, RequestMappingHandlerMapping and RequestMappingHandlerAdapter.

    The first is the implementation class of HandlerMapping, which processes the @RequestMapping annotation and registers it in the request mapping table. (We will describe in detail in the next article)

    The second is the implementation class of HandlerAdapter, which is an adapter for processing requests. To put it bluntly, it is to determine which method of which class is called, and to construct method parameters and return values. (Will be introduced in detail later in the article)

    So what's the difference between it and <context:component-scan/>? In fact, as introduced in the previous article, the <context:component-scan/> tag tells Spring to scan the classes under the specified package and register the components marked by @Component, @Controller , @Service, @Repository and other annotations.

 

    And <mvc:annotation-driven/> is to inform Spring that we enable annotation-driven. Then Spring will automatically register the beans mentioned above to the factory for us to process our requests.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326498555&siteId=291194637