SpringMVC源码解析五(HandlerMethod执行过程解析)

在获取HandlerMethodAdapter适配器之后, 调用适配器的handle()方法执行处理器, 也就是Control类中我们编写的处理方法

 AbstractHandlerMethodAdapter#handle()方法实现:

@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    /**
     * Spring默认处理适配器为:RequestMappingHandlerAdapter(注解处理器适配器)
     * {@link RequestMappingHandlerAdapter#handleInternal(HttpServletRequest,HttpServletResponse,HandlerMethod)}
     */
    return handleInternal(request, response, (HandlerMethod) handler);
}

AbstractHandlerMethodAdapter为RequestMappingHandlerAdapter的父类

RequestMappingHandlerAdapter#handleInternal()方法实现:

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

    ModelAndView mav;
    checkRequest(request);

    //如果需要,在同步块中执行invokeHandlerMethod。
    if (this.synchronizeOnSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session);
            synchronized (mutex) {
                mav = invokeHandlerMethod(request, response, handlerMethod);
            }
        }
        else {
            // No HttpSession available -> no mutex necessary
            mav = invokeHandlerMethod(request, response, handlerMethod);
        }
    }
    else {
        //完全不需要会话同步。
        /**
         * {@link RequestMappingHandlerAdapter#invokeHandlerMethod(HttpServletRequest, HttpServletResponse, HandlerMethod)}
         */
        mav = invokeHandlerMethod(request, response, handlerMethod);
    }

    if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
        if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
            applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
        }
        else {
            prepareResponse(response);
        }
    }
    return mav;
}

分析:

  1. 首先对请求进行检查, 对于不支持的请求直接抛出异常
  2. 根据是否需要进行会话同步执行相关激活HandlerMethod方法
  3. 返回执行HandlerMethod方法后返回的ModelAndView

RequestMappingHandlerAdapter#invokeHandlerMethod()方法实现:

@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    //将Request和Response进行封装
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        /**
         * 创建InvocableHandlerMethod实例,以及各个组件的配置;
         * 后面通过调用invokeAndHandle()方法执行处理器
         */
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);


        if (this.argumentResolvers != null) {
            invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        }
        if (this.returnValueHandlers != null) {
            invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        }
        invocableMethod.setDataBinderFactory(binderFactory);
        invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
        /**
         * 创建视图容器, 用于封装视图, 数据模型, 处理状态等信息
         */
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

        AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
        asyncWebRequest.setTimeout(this.asyncRequestTimeout);

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.setTaskExecutor(this.taskExecutor);
        asyncManager.setAsyncWebRequest(asyncWebRequest);
        asyncManager.registerCallableInterceptors(this.callableInterceptors);
        asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

        if (asyncManager.hasConcurrentResult()) {
            Object result = asyncManager.getConcurrentResult();
            mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
            asyncManager.clearConcurrentResult();
            if (logger.isDebugEnabled()) {
                logger.debug("Found concurrent result value [" + result + "]");
            }
            invocableMethod = invocableMethod.wrapConcurrentResult(result);
        }
        /**
         * 执行处理器
         */
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        if (asyncManager.isConcurrentHandlingStarted()) {
            return null;
        }
        /**
         * 返回ModelAndView实例, 后面进行视图解析
         */
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    finally {
        webRequest.requestCompleted();
    }
}

分析:

  1. 创建InvocableHandlerMethod实例,以及各个组件的配置,  后面通过调用invokeAndHandle()方法执行处理器
  2. 创建视图容器, 用于封装视图, 数据模型, 处理状态等信息
  3. 执行处理器方法
  4. 封装ModelAndView实例并返回, 后面进行视图解析

ServletInvocableHandlerMethod#invokeAndHandle()方法的实现:

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
    /**
     * 处理请求
     * returnValue为返回的ModelAndView实例或者ViewName
     */
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    setResponseStatus(webRequest);

    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
            mavContainer.setRequestHandled(true);
            return;
        }
    }
    else if (StringUtils.hasText(getResponseStatusReason())) {
        mavContainer.setRequestHandled(true);
        return;
    }

    mavContainer.setRequestHandled(false);
    Assert.state(this.returnValueHandlers != null, "No return value handlers");
    try {
        /**
         * 封装返回的数据信息
         */
        this.returnValueHandlers.handleReturnValue(
                returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
    catch (Exception ex) {
        if (logger.isTraceEnabled()) {
            logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
        }
        throw ex;
    }
}

分析:

  1. 处理请求
  2. 封装返回的数据信息

InvocableHandlerMethod#invokeForRequest()方法:

@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {

    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
                "' with arguments " + Arrays.toString(args));
    }
    /**
     * 执行Handler方法
     */
    Object returnValue = doInvoke(args);
    if (logger.isTraceEnabled()) {
        logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
                "] returned [" + returnValue + "]");
    }
    return returnValue;
}

分析:

  1. 获取执行HandlerMethod方法需要的参数, 也就是请求中包含的需要处理的数据
  2. 执行HandlerMethod方法

InvocableHandlerMethod#doInvoke()方法实现:

/**
 * 使用给定的参数值调用处理程序方法。
 */
protected Object doInvoke(Object... args) throws Exception {
    ReflectionUtils.makeAccessible(getBridgedMethod());
    try {
        /**
         *  获取桥接方法实例, 并执行该方法
         *  执行Control类中编写的方法
         */
        return getBridgedMethod().invoke(getBean(), args);
    }
    catch (IllegalArgumentException ex) {
        . . . . . .
    }
}

分析:

 1.  这里就是获取到HandlerMethod实例中维护的我们编写的处理方法, 然后通过反射去执行该方法对象, 注意这里获取的是桥接方法, 为什么要使用桥接方法呢? 不懂的同学可以看这篇播客: Java中什么是bridge method(桥接方法);

 2.  在invoke()方法中有一个getBean()的方法, 这个是因为我们在执行Method时需要传递一个该方法所属类的实例对象; Spring在解析Controller类时会实例化一个对象,  这里的getBean获取的就是这个对象;  在SpringMVC初始化时,  会获取该实例对象, 然后遍历该实例的所有方法,  并将该方法和该Controller对象封装到HandlerMethod实例中, 然后注册到mappingLookup这个容器中; 这些在解析三这篇博客中有详细说明;

3. getBridgedMethod().invoke(getBean(), args)实际上执行的是我们编写的处理器方法

至此, 通过适配器RequestMappingHandlerAdapter执行处理器的解析已完成;

 

相关文章:

     SpringMVC源码解析一(在Spring源码项目中搭建SpringMVC源码模块)

     SpringMVC源码解析二(请求过程解析)

     SpringMVC源码解析三(处理映射器HandlerMapping的解析)

     SpringMVC源码解析四(处理适配器HandlerAdapter的解析)

     SpringMVC源码解析五(HandlerMethod执行过程解析)

     SpringMVC源码解析六(ModelAndView解析)

     SpringMVC源码解析七(初始化过程解析

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC 是一个基于 Servlet API 构建的 Web 框架,它是 Spring Framework 的一部分,提供了 Model-View-Controller(MVC)架构模式的实现。Spring MVC 的核心思想是将应用程序的业务逻辑与视图分离,使应用程序更容易维护和扩展。 Spring MVC 的源码涉及到很多模块,比如 DispatcherServlet、HandlerMapping、HandlerAdapter、ViewResolver 等等。下面我们从 DispatcherServlet 入手,深度解析 Spring MVC 的源码。 1. DispatcherServlet DispatcherServlet 是整个 Spring MVC 框架的核心,它是一个 Servlet,所有的请求都会经过它。DispatcherServlet 的主要作用是将请求分派给相应的 HandlerMapping,然后将处理结果返回给客户端。DispatcherServlet 在初始化时会加载一些配置文件,比如 applicationContext.xml、spring-mvc.xml 等等。这些配置文件中定义了 Spring MVC 的各个组件,包括 HandlerMapping、HandlerAdapter、ViewResolver 等等。 2. HandlerMapping HandlerMapping 用来映射请求到相应的处理器,它根据请求的 URL 和其他条件来确定最终的处理器。Spring MVC 中提供了多种 HandlerMapping 实现,比如 BeanNameUrlHandlerMapping、RequestMappingHandlerMapping、SimpleUrlHandlerMapping 等等。其中,RequestMappingHandlerMapping 是最常用的 HandlerMapping 实现,它会扫描应用程序中所有带有 @Controller 注解的类,并将其中所有带有 @RequestMapping 注解的方法注册为处理器。 3. HandlerAdapter HandlerAdapter 用来确定请求处理器的类型,并调用相应的方法来处理请求。Spring MVC 中提供了多种 HandlerAdapter 实现,比如 HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter 等等。其中,AnnotationMethodHandlerAdapter 是最常用的 HandlerAdapter 实现,它会根据方法的参数类型和返回值类型动态地确定请求处理器的类型,并调用相应的方法来处理请求。 4. ViewResolver ViewResolver 用来将逻辑视图名解析为实际的视图对象,它根据逻辑视图名和其他条件来确定最终的视图对象。Spring MVC 中提供了多种 ViewResolver 实现,比如 InternalResourceViewResolver、FreeMarkerViewResolver、VelocityViewResolver 等等。其中,InternalResourceViewResolver 是最常用的 ViewResolver 实现,它会将逻辑视图名解析为 JSP 文件名,并返回一个 InternalResourceView 对象。 5. ModelAndView ModelAndView 是 Spring MVC 中最常用的视图模型对象,它包含了视图名称和模型数据。在处理请求时,请求处理器将模型数据填充到 ModelAndView 对象中,并返回一个 ModelAndView 对象作为处理结果。DispatcherServlet 会将 ModelAndView 对象传递给 ViewResolver,ViewResolver 会使用视图名称和模型数据来渲染响应结果。 以上就是 Spring MVC 源码深度解析的简要介绍,需要注意的是,Spring MVC 的源码非常庞大,涉及到很多细节问题。如果需要深入研究 Spring MVC 的源码,需要花费大量的时间和精力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值