You’ve already seen the initStrategies() method in DispatchServlet that initializes the HandlerMapping component, so let’s start there!! RequestMappingHandlerAdapter, for example.

Step 1: Spring creates the Bean instance of the HandlerAdapter interface

Because RequestMappingHandlerAdapter implements InitializingBean interface, then is called the afterPropertiesSet () method.

public void afterPropertiesSet(a) {
   // Initialize ControllerAdvice
   initControllerAdviceCache();

   if (this.argumentResolvers == null) {
      // Initialize some built-in parameter parsers
      List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
      this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
   }
    // Initialize some built-in initialization binding parameter parsers
   if (this.initBinderArgumentResolvers == null) {
      List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
      this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
   }
   if (this.returnValueHandlers == null) {
      // Initialize some built-in return value (output parameter) parsers
      List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
      this.returnValueHandlers = newHandlerMethodReturnValueHandlerComposite().addHandlers(handlers); }}Copy the code

And here, we can see that the container helped us initialize a little bitParameter parsers and return value parsersFor later use. Get all the annotations here as well@ControllerAdviceAnnotated beans.

Step 2: Get all the Bean instances of the HandlerAdapter interface

private void initHandlerAdapters(ApplicationContext context) {
   this.handlerAdapters = null;
   DetectAllHandlerAdapters Default to true. Programmers can set them manually
   if (this.detectAllHandlerAdapters) {
      // Find all implementation classes that implement the HandlerAdapter interface in all containers, including the parent.
      Map<String, HandlerAdapter> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true.false);
      if(! matchingBeans.isEmpty()) {// Assign sort
         this.handlerAdapters = new ArrayList<>(matchingBeans.values());
         AnnotationAwareOrderComparator.sort(this.handlerAdapters); }}else {
      try {
         // Get the Bean instance beanName="handlerAdapter" from the container and assign it to handlerAdapters
         HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
         this.handlerAdapters = Collections.singletonList(ha);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Ignore, we'll add a default HandlerAdapter later.}}/ / if the developer has no configuration HandlerAdapter, then from the DispatcherServlet. The properties file
   // Load the default HandlerAdapter.
   if (this.handlerAdapters == null) {
      this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); }}Copy the code

Step 3: Use the Bean instance of the HandlerAdapter interface

MappedHandler is a HandlerExecutionChain that is looked up by HandlerMapping.

// mappedHandler.gethandler () : Gets the HandlerMethod
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

. / / omit code, HandlerInterceptor preHandle () : execute the interceptor preHandle () method. Return true, continue execution.
// return false, terminate to continue.

// Execute handleMethod through HandlerAdapter
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());


// Return the appropriate HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   if (this.handlerAdapters ! =null) {
      for (HandlerAdapter adapter : this.handlerAdapters) {
         if (adapter.supports(handler)) {
            returnadapter; }}}}Copy the code

Through the current request correspondingHandlerMethodGo find the right oneHandlerAdapter. Here, the final return is RequestMappingHandlerAdapter.

// AbstractHandlerMethodAdapter.java
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
   / / the real processing logic, on RequestMappingHandlerAdapter subclass implementation.
   return handleInternal(request, response, (HandlerMethod) handler);
}

protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

   ModelAndView mav;
   checkRequest(request);
   // Execute handler method
   mav = invokeHandlerMethod(request, response, handlerMethod);
   return mav;
}

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   ServletWebRequest webRequest = new ServletWebRequest(request, response);
   try {
      // Initialize the data binding project. As you can see in the figure below, there are many Converters
      WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
      // Initialize the Model factory
      ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

      // Set up some parameter parsers, code omitted........
      ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
      / /...

      ModelAndViewContainer mavContainer = new ModelAndViewContainer();
      // Get all the attributes of the current request flashMap and add them to ModelAndViewContainer
      mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
      // Get the @modelAttribute and SessionAttribute values for the current request
      modelFactory.initModel(webRequest, mavContainer, invocableMethod);
      mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

      // Get the parameter, call handler method, and get the return value.
      invocableMethod.invokeAndHandle(webRequest, mavContainer);

      // Create the ModelAndView object with model and viewName, set the View, and return the object.
      // 如果是RestController,则 ModelAndView = null
      return getModelAndView(mavContainer, modelFactory, webRequest);
   }
   finally{ webRequest.requestCompleted(); }}Copy the code

From the code, we know thatinvocableMethod.invokeAndHandle(webRequest, mavContainer);Is the most important treatment method, all the details can be learned in it.

Four,

HandlerAdapter parses input parameters (Model, Session, FlashMap…) during execution. After parsing, execute the business logic in handler, then parse the returnValue, and finally return ModelAndView.