springMVC源碼解析--HandlerMethodArgumentResolverComposite參數(shù)解析器集合(二)
springMVC源碼分析--RequestParamMethodArgumentResolver參數(shù)解析器(三)
HandlerMethodArgumentResolver是用來為處理器解析參數(shù)的欧漱,主要用在HandlerMethod中,每個Resolver對應(yīng)一種類型的參數(shù)丰涉,其實現(xiàn)類特別的多颜价。
HandlerMethodArgumentResolver接口及其實現(xiàn)類如下:
HandlerMethodArgumentResolver的接口定義如下:
(1)supportsParameter 用于判斷是否支持對某種參數(shù)的解析
(2)resolveArgument 將請求中的參數(shù)值解析為某種對象
public interface HandlerMethodArgumentResolver {
/**
* Whether the given {@linkplain MethodParameter method parameter} is
* supported by this resolver.
* @param parameter the method parameter to check
* @return {@code true} if this resolver supports the supplied parameter;
* {@code false} otherwise
*/
//判斷是否支持某種類型的函數(shù)參數(shù)
boolean supportsParameter(MethodParameter parameter);
/**
* Resolves a method parameter into an argument value from a given request.
* A {@link ModelAndViewContainer} provides access to the model for the
* request. A {@link WebDataBinderFactory} provides a way to create
* a {@link WebDataBinder} instance when needed for data binding and
* type conversion purposes.
* @param parameter the method parameter to resolve. This parameter must
* have previously been passed to
* {@link #supportsParameter(org.springframework.core.MethodParameter)}
* and it must have returned {@code true}
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @param binderFactory a factory for creating {@link WebDataBinder} instances
* @return the resolved argument value, or {@code null}.
* @throws Exception in case of errors with the preparation of argument values
*/
//解析請求中的參數(shù)為某個函數(shù)的參數(shù)對象
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}
HandlerMethodArgumentResolver的執(zhí)行流程:
參數(shù)的處理是在InvocableHandlerMethod中,當執(zhí)行具體的請求處理時執(zhí)行invokeForRequest函數(shù)
public class InvocableHandlerMethod extends HandlerMethod {
.....
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
//獲取執(zhí)行Controller的函數(shù)的參數(shù)對象
Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
if(this.logger.isTraceEnabled()) {
this.logger.trace("Invoking \'" + ClassUtils.getQualifiedMethodName(this.getMethod(), this.getBeanType()) + "\' with arguments " + Arrays.toString(args));
}
Object returnValue = this.doInvoke(args);
if(this.logger.isTraceEnabled()) {
this.logger.trace("Method [" + ClassUtils.getQualifiedMethodName(this.getMethod(), this.getBeanType()) + "] returned [" + returnValue + "]");
}
return returnValue;
}
}
具體的參數(shù)解析器的選擇和使用參數(shù)解析器去解析參數(shù)的實現(xiàn)都在getMethodArgumentValues中晒来,首先springMVC在啟動時會將所有的參數(shù)解析器放到HandlerMethodArgumentResolverComposite钞诡,HandlerMethodArgumentResolverComposite是所有參數(shù)的一個集合,接下來就是從HandlerMethodArgumentResolverComposite參數(shù)解析器集合中選擇一個支持對parameter解析的參數(shù)解析器湃崩,接下來就使用支持參數(shù)解析的解析器進行參數(shù)解析荧降。
private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//獲取執(zhí)行的具體函數(shù)的參數(shù)
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
//獲取參數(shù)值對象
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
//首先判斷是否有參數(shù)解析器支持參數(shù)parameter,采用職責(zé)鏈的設(shè)計模式
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
//如果參數(shù)解析器支持解析參數(shù)parameter攒读,那么解析參數(shù)成Controller的函數(shù)需要的格式
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
}
throw ex;
}
}
if (args[i] == null) {
String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
throw new IllegalStateException(msg);
}
}
//返回參數(shù)值
return args;
}
以上代碼會將我們通過鏈接提交的參數(shù)值轉(zhuǎn)換為對象值朵诫。