HandlerMethod類源碼解析

HandlerMethod類用於封裝控制器方法信息,包含類信息、方法Method對象、參數、註解等信息,具體的接口請求是可以根據封裝的信息調用具體的方法來執行業務邏輯;

HandlerMethod有三個子類分別是InvocableHandlerMethod、ServletInvocableHandlerMethod、ConcurrentResultHandlerMethod,類的關係圖如下:

在這裏插入圖片描述

1.HandlerMethod類源碼詳解
public class HandlerMethod {
	//bean名稱,調試的時候看到是字符串控制器名稱(首字母小寫)
	private final Object bean;
  //bean工廠類,個人調試傳入的是DefaultListableBeanFactory
	@Nullable
	private final BeanFactory beanFactory;
	//方法所屬類
	private final Class<?> beanType;
	//控制器方法
	private final Method method;
	//橋接方法,如果method是原生的,這個屬性就是method
	private final Method bridgedMethod;
	//封裝方法參數實例
	private final MethodParameter[] parameters;
	//Http狀態碼
	@Nullable
	private HttpStatus responseStatus;
	//ResponseStatus註解的reason值
	@Nullable
	private String responseStatusReason;
	//使用createWithResolvedBean方法創建的HttpMethod方法對象
	@Nullable
	private HandlerMethod resolvedFromHandlerMethod;
	//getInterfaceParameterAnnotations獲取
	@Nullable
	private volatile List<Annotation[][]> interfaceParameterAnnotations;
	//類描述,使用initDescription方法解析beanType和method獲得
	private final String description;
}
2.InvocableHandlerMethod類詳解

InvocableHandlerMethod類是HandlerMethod的直接子類,該類中新增了對請求參數解析的參數解析程序,request請求時的回調方法invokeForRequest和doInvoke(建議閱讀HandlerAdapter源碼解析)

request請求會在RequestMappingHandlerAdapter類中的handleInternal方法進行回調,回調方法的源碼如下:

	/**
	* 獲取request請求參數,調用控制器方法
	**/
  @Nullable
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//獲取request請求方法的參數
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
		return doInvoke(args);
	}

doInvoke方法源碼:

	/**
	* 使用給定的參數調用控制器方法
	**/
	@Nullable
	protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
      //調用真實最終的控制器方法,並返回執行後的結果
			return getBridgedMethod().invoke(getBean(), args);
		}
		catch (IllegalArgumentException ex) {
			assertTargetBean(getBridgedMethod(), getBean(), args);
			String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
			throw new IllegalStateException(formatInvokeError(text, args), ex);
		}
		catch (InvocationTargetException ex) {
			// Unwrap for HandlerExceptionResolvers ...
			Throwable targetException = ex.getTargetException();
			if (targetException instanceof RuntimeException) {
				throw (RuntimeException) targetException;
			}
			else if (targetException instanceof Error) {
				throw (Error) targetException;
			}
			else if (targetException instanceof Exception) {
				throw (Exception) targetException;
			}
			else {
				throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
			}
		}
	}
3.ServletInvocableHandlerMethod類詳解

ServletInvocableHandlerMethod類繼承了InvocableHandlerMethod類,新增了處理返回值HandlerMethodReturnValueHandler的能力,並且新增了調用控制器方法的回調方法;

回調invokeAndHandle方法源碼如下:

	/**
	 * Invoke the method and handle the return value through one of the
	 * configured {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers}.
	 * @param webRequest the current request
	 * @param mavContainer the ModelAndViewContainer for this request
	 * @param providedArgs "given" arguments matched by type (not resolved)
	 */
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//調用父類InvocableHandlerMethod的回調方法,並返回調用接口控制器方法的返回結果
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				disableContentCachingIfNecessary(webRequest);
				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 {
      //將控制器返回的結果交給HandlerMethodReturnValueHandler來處理
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}
4.ConcurrentResultHandlerMethod類詳解

ConcurrentResultHandlerMethod是ServletInvocableHandlerMethod的一個內部類,也是它的子類,支持異常調用結果處理(暫時沒有發現使用的場景)

GitHub地址:https://github.com/mingyang66/spring-parent/tree/master/doc/base

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章