springBoot 获取注解参数的原理

springBoot 获取注解参数的原理

原理图

  1. 先得到请求的request

  2. 在获取可以处理请求的方法的Mapping映射器

    DispatcherServlet中的
    doDispatch方法
    // Determine handler for the current request.
    mappedHandler = getHandler(processedRequest);
  3. 判断每个参数带有注解是哪个,是否存在相应的解析器

    • 寻找合适的处理适配器

      DispatcherServlet中的
      doDispatch方法
      // Determine handler adapter for the current request.
      HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

    • 寻找可以处理相应注解的处理器
    第一步
    DispatcherServlet中的
    doDispatch方法
    // Actually invoke the handler.
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    第二步
    RequestMappingHandlerAdapter中的
    handleInternal方法
    // No synchronization on session demanded at all...
    mav = invokeHandlerMethod(request, response, handlerMethod);
    invokeHandlerMethod方法
    invocableMethod.invokeAndHandle(webRequest, mavContainer);
    第三步
    ServletInvocableHandlerMethod中的
    invokeAndHandle方法
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    第四步
    InvocableHandlerMethod类中的
    invokeForRequest方法
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);//获取请求的参数
    第五步
    InvocableHandlerMethod类中的
    getMethodArgumentValues方法
    if (!this.resolvers.supportsParameter(parameter)) {//寻找处理相关注解的处理器,并保存到缓存中 supportsParameter(parameter)从这里进入的
    throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
    }
    try {
    args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
    }
    第六步
    HandlerMethodArgumentResolverComposite类中的
    @Nullable
    private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
    HandlerMethodArgumentResolver result =
    this.argumentResolverCache.get(parameter);//从缓存中获取,开始肯定没有
    if (result == null) {
    //增强for循环中选择合适的处理器 27个
    for (HandlerMethodArgumentResolver resolver :
    this.argumentResolvers) {
    if (resolver.supportsParameter(parameter)) {
    result = resolver;
    //保存到缓存中
    this.argumentResolverCache.put(parameter, result);
    break;
    }
    }
    }
    return result;
    }

    • 通过注解处理器获取参数

      第一步
      InvocableHandlerMethod类中的
      getMethodArgumentValues方法
      try {
      args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); //真正开始获取参数
      }
      第二步
      HandlerMethodArgumentResolverComposite类中的
      resolveArgument方法中
      //获取参数对应注解的处理器
      HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
      getArgumentResolver方法中
      //从缓存中获取,由于开始的之前往缓存中存入了,所以现在可以直接拿,如果没有下面还有可以循环寻找
      HandlerMethodArgumentResolver result =
      this.argumentResolverCache.get(parameter);
      AbstractNamedValueMethodArgumentResolver类中的
      resolveArgument方法
      Object resolvedName =
      resolveEmbeddedValuesAndExpressions(namedValueInfo.name);//获取参数名
      Object arg = resolveName(resolvedName.toString(),
      nestedParameter, webRequest);//获取参数值
      //具体怎么获取
      PathVariableMethodArgumentResolver类中的
      resolveName方法
      protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
      Map<String, String> uriTemplateVars = (Map<String, String>) request.getAttribute(//直接从request请求域中获取
      HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
      return (uriTemplateVars != null ? uriTemplateVars.get(name) : null);//在通过参数名称确定是哪一个
      }
    • 获取参数完成后,会调用InvocableHandlerMethod来中的doInvoke方法继续反射调用方法

      InvocableHandlerMethod类中的
      doInvoke方法
      return method.invoke(getBean(), args);
posted @   水三丫  阅读(1308)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示