网络知识 娱乐 08初始化HandlerAdapter并执行Handler或者HandlerExecution

08初始化HandlerAdapter并执行Handler或者HandlerExecution

内容概览

到目前为止已经找为当前的HTTP请求找到了Handler或者HandlerExecution,接下来要实现的就是执行具体的业务方法。这个执行操作是由能处理此Handler的HandlerAdapter进行完成。

  • HandlerAdapter介绍
  • 实际应用使用的RequestMappingHandlerAdapter的初始化
  • 从注册的HandlerAdapter列表中找到能处理当前找到的Handler的HandlerAdapter
  • HandlerAdapter的执行

HandlerAdapter介绍

从spring-mvc的执行流程介绍中知道HandlerAdapter的功能有以下两点:

  1. 是否匹配当前的Handler或者HandlerExecution
  2. 使用匹配的HandlerAdapter去调用执行

n /**n * Given a handler instance, return whether or not this HandlerAdapter can supportn * it. Typical HandlerAdapter will base the decision on the handler type.n * HandlerAdapters will usually only support one handler type each.n */n boolean supports(Object handler);nn /**n * Use the given handler to handle this request.The workflow that is requiredn * may vary widely.n */n @Nullablen ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;n

这里列出了HandlerAdapter的两个重要方法。

  • 为当前的Handler找寻能够匹配的HandlerAdapter
  • handle方法就是匹配当前Handler的HandlerAdapter调用去执行真正的业务执行逻辑。 至于这个方法的返回值ModelAndView暂时不会使用到所以就不具体描述了。

RequestMappingHandlerAdapter的逻辑

和HandlerMapping的使用实际是RequestMappingHandlerMapping类似,HandlerAdapter在案例中实际使用的是RequestMappingHandlerAdapter。

RequestMappingHandlerAdapter类结构图

08初始化HandlerAdapter并执行Handler或者HandlerExecution

把类结构图精简出来发现还是那个老套路。HandlerAdapter接口定义了核心的方法,AbstractHandlerMethodAdapter实现接口完成统一的工作之后,在定义一系列模版方法,最后是具体的特性子类实现模版方法的逻辑。

AbstractHandlerMethodAdapter的实现

public abstract class AbstractHandlerMethodAdapter implements HandlerAdapter {nnn protected abstract boolean supportsInternal(HandlerMethod handlerMethod);nn @Nullablen protected abstract ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;nnn public AbstractHandlerMethodAdapter() {n }nn @Overriden public boolean supports(Object handler) {n return (handler instanceof HandlerMethod && supportsInternal(((HandlerMethod) handler)));n }nnn @Overriden public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {n return handleInternal(request, response, ((HandlerMethod) handler));n }n}nn

可以看到目前AbstractHandlerMethodAdapter实现了HandlerAdapter接口后,做了基本的操作之后,具体的内容都交给子类了。

RequestMappingHandlerAdapter的实现

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {nn /**n * Always return true since any method argument and return valuen * type will be processed in some way. A method argument not recoginzedn * by any HandlerMethodArgumentResolver is interpreted as a request parametern * if it is a simple type, or as a model attribute otherwise. A return valuen * not recoginzed by any HandlerMethodReturnValueHandler will be interpretedn * as a model attributen */n @Overriden protected boolean supportsInternal(HandlerMethod handlerMethod) {n return true;n }nn @Overriden protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {n return invokeHandlerMethod(request, response, handlerMethod);n }nn @Nullablen protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {nn ServletWebRequest webRequest = new ServletWebRequest(request, response);nn ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);nn ModelAndViewContainer mavContainer = new ModelAndViewContainer();nn //对于@ResponseBody的情况,将调用业务方法,同时将方法返回值放到response的body里n invocableMethod.invokeAndHandle(webRequest, mavContainer);nn //这里返回一个ModelAndView, 对于@ResponseBody的返回内容已经写进response的body中, 这里要返回nulln// return getModelAndView(mavContainer, modelFactory, webRequest);n return null;n }nnn protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {n return new ServletInvocableHandlerMethod(handlerMethod);n }n}n

目前的RequestMappingHandlerAdapter也比较简单。

  • supportsInternal方法直接返回true,表示支持所有的Handler或者HandlerExecution。 任何方法参数和返回值的Handler或者HandlerExecution都有具体的处理方式。对于无法识别的参数如果是简单类型则作为请求参数,否则作为请求的对象模型,返回类型也类似。因为目前easy-spring不准备测试带有参数的场景,所以对参数绑定就暂时不做过多描述,先把核心流程完成。
  • handleInternal中实际上会做一些同步校验等操作,这里也是为了简化省略了校验,直接调用了内部方法invokeHandlerMethod并返回
  • invokeHandlerMethod是RequestMappingHandlerAdapter完成业务方法调用的地方,但是具体的调用是由专门的调用体系ServletInvocableHandlerMethod完成的

ServletInvocableHandlerMethod业务方法调用体系类结构图

08初始化HandlerAdapter并执行Handler或者HandlerExecution

ServletInvocableHandlerMethod继承InvocableHandlerMethod。

ServletInvocableHandlerMethod能够通过注册的HandlerMethodReturnValueHandler返回处理值,并且还支持方法级别的@ResponseStatus注解设置响应状态。

所以调用业务方法的核心操作类还是InvocableHandlerMethod,其他都是辅助(设置状态码)。

ServletInvocableHandlerMethod的实现

public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {nnn public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) {n super(handlerMethod);n }nn public ServletInvocableHandlerMethod(Object bean, Method method) {n super(bean, method);n }nnn public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,n Object... provideArgs) throws Exception {n //这里会进行业务方法的实际调用n Object returnValue = invokeForRequest(webRequest, mavContainer, provideArgs);n if (null != returnValue) {n System.out.println("return value===>" + returnValue);n }n }n}nn

在ServletInvocableHandlerMethod的invokeAndHandle方法里先调用父类的方法invokeForRequest完成业务方法的调用。这里将业务方法返回的内容进行了输出,在测试的时候可以看到。

InvocableHandlerMethod的实现

public class InvocableHandlerMethod extends HandlerMethod {nn private static final Object[] EMPTY_ARGS = new Object[0];nn public InvocableHandlerMethod(HandlerMethod handlerMethod) {n super(handlerMethod);n }nn public InvocableHandlerMethod(Object bean, Method method) {n super(bean, method);n }nn /**n * Invoke the method after resolving its argument values in the context of then * given request.n * <p>n * Argument values are commonly resolved through {@link HandlerMethodArgumentResolver}.n */n @Nullablen public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,n Object... provideArgs) throws Exception {nn Object[] args = getMethodArgumentValues(request, mavContainer, provideArgs);n return doInvoke(args);n }nn protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,n Object... provideArgs) throws Exception {n return EMPTY_ARGS;n }nn @Nullablen protected Object doInvoke(Object... args) {n Method method = getBridgedMethod();n try {n return method.invoke(getBean(), args);n } catch (IllegalAccessException | InvocationTargetException e) {n throw new RuntimeException(e);n }n }n}nn

在invokeForRequest方法里首先为当前方法准备的参数。为了简化目前没有做参数的场景直接返回了一个空的参数,然后就是doInvoke方法。

doInvoke方法里就是很熟悉的JDK反射内容了。

RequestMappingHandlerAdapter的初始化

业务模块中声明使用的HandlerAdapter

在业务模块的配置文件中,声明HandlerAdapter这个bean。

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>n

新增一行HandlerAdapter的声明。

DispatcherServlet中完成HandlerAdapter的初始化策略

在DispatcherServlet的initStrategies初始化策略方法中,新增初始化HandlerAdapter的逻辑

protected void initStrategies(ApplicationContext context) {nn initHandlerMappings(context);n initHandlerAdapters(context);n }nn private void initHandlerAdapters(ApplicationContext context) {n this.handlerAdapters = null;n //Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.n Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);n if (!matchingBeans.isEmpty()) {n this.handlerAdapters = new ArrayList<>(matchingBeans.values());n //We keep HandlerAdapters in sorted order.n AnnotationAwareOrderComparator.sort(this.handlerAdapters);n }n }n

DispatcherServlet的doDispatch中增加查找匹配的HandlerAdapter

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {nn HttpServletRequest processedRequest = request;nnn HandlerExecutionChain mappedHandler = getHandler(processedRequest);n if (null == mappedHandler) {n noHandlerFound(processedRequest, response);n return;n }nn HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());nn ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());nn }nn protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {n if (null != this.handlerAdapters) {n for (HandlerAdapter adapter : this.handlerAdapters) {n if (adapter.supports(handler)) {n return adapter;n }n }n }n throw new ServletException("No adapter for handler [" + handler +n "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");n }n

在doDispatch方法中调用getHandlerAdapter查找能够支持当前HandlerExecutionChain的HandlerAdapter,如果找不到则抛出异常,否则调用其handle方法出发业务方法的调用。

HandlerAdapter的执行流程

08初始化HandlerAdapter并执行Handler或者HandlerExecution

  1. 匹配到的HandlerAdapter调用handle方法
  2. 调用模版方法handleInternal进行简单的同步检查等操作
  3. 在内部方法invokeHandlerMethod里调用ServletInvocableHandlerMethod模块实现业务方法的调用
  4. ServletInvocableHandlerMethod开始准备调用业务方法

测试

启动example-easy-spring项目调用暴露出来的端点。可以看到业务方法被调用,以及输出返回的结果。

return value===>[beanController, org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0, org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0]n