private WebDataBinder resolveModelAttribute(
      String attrName,
      MethodParameter methodParam,
      ExtendedModelMap implicitModel,
      NativeWebRequest webRequest,
      Object handler)
      throws Exception {

    // Bind request parameter onto object...
    String name = attrName;
    if ("".equals(name)) {
      name = Conventions.getVariableNameForParameter(methodParam);
    }
    Class<?> paramType = methodParam.getParameterType();
    Object bindObject;
    if (implicitModel.containsKey(name)) {
      bindObject = implicitModel.get(name);
    } else if (this.methodResolver.isSessionAttribute(name, paramType)) {
      bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
      if (bindObject == null) {
        raiseSessionRequiredException(
            "Session attribute '" + name + "' required - not found in session");
      }
    } else {
      bindObject = BeanUtils.instantiateClass(paramType);
    }
    WebDataBinder binder = createBinder(webRequest, bindObject, name);
    initBinder(handler, name, binder, webRequest);
    return binder;
  }
  public final void updateModelAttributes(
      Object handler,
      Map<String, Object> mavModel,
      ExtendedModelMap implicitModel,
      NativeWebRequest webRequest)
      throws Exception {

    if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
      for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
        this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
      }
    }

    // Expose model attributes as session attributes, if required.
    // Expose BindingResults for all attributes, making custom editors available.
    Map<String, Object> model = (mavModel != null ? mavModel : implicitModel);
    if (model != null) {
      try {
        String[] originalAttrNames = model.keySet().toArray(new String[model.size()]);
        for (String attrName : originalAttrNames) {
          Object attrValue = model.get(attrName);
          boolean isSessionAttr =
              this.methodResolver.isSessionAttribute(
                  attrName, (attrValue != null ? attrValue.getClass() : null));
          if (isSessionAttr) {
            if (this.sessionStatus.isComplete()) {
              implicitModel.put(MODEL_KEY_PREFIX_STALE + attrName, Boolean.TRUE);
            } else if (!implicitModel.containsKey(MODEL_KEY_PREFIX_STALE + attrName)) {
              this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);
            }
          }
          if (!attrName.startsWith(BindingResult.MODEL_KEY_PREFIX)
              && (isSessionAttr || isBindingCandidate(attrValue))) {
            String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName;
            if (mavModel != null && !model.containsKey(bindingResultKey)) {
              WebDataBinder binder = createBinder(webRequest, attrValue, attrName);
              initBinder(handler, attrName, binder, webRequest);
              mavModel.put(bindingResultKey, binder.getBindingResult());
            }
          }
        }
      } catch (InvocationTargetException ex) {
        // User-defined @InitBinder method threw an exception...
        ReflectionUtils.rethrowException(ex.getTargetException());
      }
    }
  }