Spring注解@ModelAttribute

当spring管理的对象的方法或者参数出现了注解@ModelAttribute时候,意味着这个属性会被注入

@ModelAttribute
	public Book get(@RequestParam(required=false) String id) {
		Book entity = null;
		if (StringUtils.isNotBlank(id)){
			entity = bookService.get(id);
		}
		if (entity == null){
			entity = new Book();
		}
		return entity;
	}

当这个类中所有方法被调用之前这个方法都会被执行放入

ModelAndViewContainer

这个容器中去,当对应的方法被执行的时候如果没有传入参数会去这个容器中找到匹配参数继而传入到方法调用

@RequestMapping(value = "form")
	public String form(Book book, Model model) {
		model.addAttribute("book", book);
		return "ibook/book/bookForm";
	}

当这个方法再被调用时候之前查出来的Book对象会自然被传入,而前台并未传入,此方法适合修改一个对象的操作如update,只需要传入ModelAttribute对应方法的参数即可

请求流程图如下:

212140_UFYP_867830.png

 

当请求到RequestMappingHandlerAdapter对象的invokeHandleMethod方法

private ModelAndView invokeHandleMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);

		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
		ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);

		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
//初始化ModelAttribute注解方法
		modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
		mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

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

		final 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 + "]");
			}
			requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);
		}

		requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

		if (asyncManager.isConcurrentHandlingStarted()) {
			return null;
		}

		return getModelAndView(mavContainer, modelFactory, webRequest);
	}

 

ModelFactory的initModel如下

public void initModel(NativeWebRequest request, ModelAndViewContainer mavContainer, HandlerMethod handlerMethod)
			throws Exception {
        //抽取出目标类的所有方法
		Map<String, ?> attributesInSession = this.sessionAttributesHandler.retrieveAttributes(request);
		mavContainer.mergeAttributes(attributesInSession);
        //设置ModelAttribute注解的值
		invokeModelAttributeMethods(request, mavContainer);

		for (String name : findSessionAttributeArguments(handlerMethod)) {
			if (!mavContainer.containsAttribute(name)) {
				Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
				if (value == null) {
					throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");
				}
				mavContainer.addAttribute(name, value);
			}
		}
	}

invokeModelAttributeMethods方法如下:

private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer mavContainer)
			throws Exception {

		for (InvocableHandlerMethod attrMethod : this.attributeMethods) {
            //获取含有注解的对应方法名
			String modelName = attrMethod.getMethodAnnotation(ModelAttribute.class).value();
			if (mavContainer.containsAttribute(modelName)) {
				continue;
			}

			Object returnValue = attrMethod.invokeForRequest(request, mavContainer);

			if (!attrMethod.isVoid()){
				String returnValueName = getNameForReturnValue(returnValue, attrMethod.getReturnType());
				if (!mavContainer.containsAttribute(returnValueName)) {
					mavContainer.addAttribute(returnValueName, returnValue);
				}
			}
		}
	}

 

此时便把注解解析完成值都放入到了mavContainer容器中。

此时回到执行目标方法流程图既是:RequestMappingHandlerAdapter的invokeHandleMethod方法

 

requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

214044_bl5g_867830.png

到ServletInvocableHandlerMethod的invokeAndHandle

public final void invokeAndHandle(ServletWebRequest webRequest,
      ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
   //执行目标函数
   Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

   setResponseStatus(webRequest);

   if (returnValue == null) {
      if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
         mavContainer.setRequestHandled(true);
         return;
      }
   }
   else if (StringUtils.hasText(this.responseReason)) {
      mavContainer.setRequestHandled(true);
      return;
   }

   mavContainer.setRequestHandled(false);

   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;
   }
}

 

到InvokableHandlerMethod的invokeForRequest

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

   Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
   if (logger.isTraceEnabled()) {
      StringBuilder sb = new StringBuilder("Invoking [");
      sb.append(getBeanType().getSimpleName()).append(".");
      sb.append(getMethod().getName()).append("] method with arguments ");
      sb.append(Arrays.asList(args));
      logger.trace(sb.toString());
   }
   Object returnValue = invoke(args);
   if (logger.isTraceEnabled()) {
      logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
   }
   return returnValue;

}

 

 

 

 

转载于:https://my.oschina.net/u/867830/blog/1526532

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值