spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework 。
链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。
在@EnableWebMvc注解,激活mvc的一些组件时,其中就创建了 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter。
这两个类本身也是 InitializingBean 的实现,所以在创建后会调用 afterPropertiesSet() 初始化。
1 RequestMappingHandlerMapping 的初始化
RequestMappingHandlerMapping 主要封装 url、方法上的 @RequestMapping 注解信息、HandlerMethod、跨域配置等的一些映射关系,以及提供与此相关的一些操作方法。
1.1 主要流程
方法调用流程:
afterPropertiesSet() -> super.afterPropertiesSet() -> initHandlerMethods() -> processCandidateBean() -> detectHandlerMethods()
initHandlerMethods() 源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
protected void initHandlerMethods() {
// 获取ApplicationContext容器中所有的beanName,循环判断不是以scopedTarget.开头的beanName执行候选操作。
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
// TODO 执行操作。
processCandidateBean(beanName);
}
}
// 一个钩子方法,在查找并封装完完所有的处理方法各种映射关系之后,进行调用。
handlerMethodsInitialized(getHandlerMethods());
}
}
|
首先从容器中获取所有的 beanName 的数组。
遍历这些 beanName,将其作为参数依次调用 processCandidateBean()。
detectHandlerMethods() 源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
Class<?> userType = ClassUtils.getUserClass(handlerType);
// 获取方法 - RequestMappingInfo 的映射
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
// 根据类和方法上RequestMapping中的value,结合成一个路径封装成RequestMappingInfo返回
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
// TODO 注册处理方法
methods.forEach((method, mapping) -> {
// 获取到可调用的方法
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// TODO 注册 HandlerMethod
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
}
|
- 遍历类中所有方法,获取 Method - RequestMappingInfo 的映射关系。
- 注册 HandlerMethod。
1.2 获取 Method-RequestMappingInfo 映射
selectMethods() 源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public final class MethodIntrospector {
public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {
final Map<Method, T> methodMap = new LinkedHashMap<>();
Set<Class<?>> handlerTypes = new LinkedHashSet<>();
Class<?> specificHandlerType = null;
if (!Proxy.isProxyClass(targetType)) {
specificHandlerType = ClassUtils.getUserClass(targetType);
handlerTypes.add(specificHandlerType);
}
// 获取类实现的所有接口
handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));
for (Class<?> currentHandlerType : handlerTypes) {
final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
ReflectionUtils.doWithMethods(currentHandlerType, method -> {
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
T result = metadataLookup.inspect(specificMethod);
if (result != null) {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// inspect() 调用到了外层的匿名对象
if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
// 方法-RequestMappingInfo映射
methodMap.put(specificMethod, result);
}
}
}, ReflectionUtils.USER_DECLARED_METHODS);
}
return methodMap;
}
}
|
- 遍历本类以及所有实现接口的 Class 对象。
- 获取到该 Class 中定义的所有方法、遍历。
- 调用外层匿名对象中的 inspect 方法,获取到 result,即会调用到 getMappingForMethod(),最终获取到 RequestMappingInfo 实例。
- 将当前方法与获取到的 RequestMappingInfo,建立映射管理,存储到一个 map 集合中。
getMappingForMethod() 中,调用了 createRequestMappingInfo(),源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
// 步骤 1
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
// TODO 创建 RequestMappingInfo,这里完成了 @RequestMappingInfo 的扫描及封装操作。
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
// 将类上的 @RequestMappingInfo 和方法上的 @RequestMappingInfo 结合。
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).build().combine(info);
}
}
return info;
}
// 步骤 2
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
// 扫描 @RequestMapping 注解,将必要的信息封装成 RequestMappingInfo
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition<?> condition = (element instanceof Class ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
// 步骤 3
protected RequestMappingInfo createRequestMappingInfo(
RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
// 这里面封装了方法上 @RequestMapping 注解的一些参数值。
RequestMappingInfo.Builder builder = RequestMappingInfo
.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
.methods(requestMapping.method())
.params(requestMapping.params())
.headers(requestMapping.headers())
.consumes(requestMapping.consumes())
.produces(requestMapping.produces())
.mappingName(requestMapping.name());
if (customCondition != null) {
builder.customCondition(customCondition);
}
return builder.options(this.config).build();
}
}
|
如果方法上有注解 @RequestMapping,则封装成 RequestMappingInfo。内部封装了方法、以及 @RequestMapping 中设置的一系列参数值。
1.3 注册 HandlerMethod
在获取到 方法 - RequestMappingInfo
映射关系后,循环这个map,依次对其进行注册。
源码如下:
1
2
3
4
5
6
7
|
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
// TODO 注册映射信息
this.mappingRegistry.register(mapping, handler, method);
}
}
|
register() 源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
// 封装HanlderMethod
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
// TODO 封装 RequestMappingInfo - HandlerMethod 映射关系
this.mappingLookup.put(mapping, handlerMethod);
// url - mapping 映射关系,mapping-handlerMethod的映射关系。这两个map很重要。请求url匹配到处理方法,就是通过这两个关系映射来匹配的。
// TODO 获取到RequestMappingInfo中的 paths(用于匹配请求路径的url),遍历,依次建立 url - RequestMappingInfo的映射关系。
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
// 建立 url - RequestMappingInfo的映射关系。
// 当一个请求过来的时候,就可以根据url找到对应的RequestMappingInfo,通过RequestMappingInfo
// 就可以在 mappingLookup 中找到 handlerMethod,即controller中的方法。
this.urlLookup.add(url, mapping);
}
// requestMappingInfo的名称策略,将名称 - requestMappingInfo的映射缓存到 nameLookup。
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
// 缓存跨域配置信息。将handlerMethod和corsConfig的映射缓存到 corsLookup
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
// RequestMappingInfo - MappingRegistration映射。
// MappingRegistration 中封装了 RequestMappingInfo、HandlerMethod、directUrls、mappingName信息。
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
}
|
方法流程:
- 创建 HandlerMethod。
- 将 RequestMappingInfo - HandlerMethod 的映射关系存储到 mappingLookup。
- 查找到 RequestMappingInfo 中所有的 url信息。
- 将 url - RequestMappingInfo 的映射关系,存储到 urlLookup。
- 初始化跨域相关配置信息,将 HandlerMethod - corsConfig 映射关系存储到 corsLookup。
- 将 RequestMappingInfo、HandlerMethod、directUrls、mappingName 信息封装到 MappingRegistration,并以 RequestMappingInfo 作为键值,缓存到变量 registry。
mappingRegistry 是 RequestMappingHandlerMapping 中的一个成员变量,最终,上面流程获取到的信息都会注册到这里。
它的声明如下:
1
2
3
4
5
|
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
/** 注册mapping,这里面封装了一系列的映射信息,url-requestMappingInfo、requestMappingInfo-handlerMethod等的映射。 */
private final MappingRegistry mappingRegistry = new MappingRegistry();
}
|
MappingRegistry 的数据结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class MappingRegistry {
/** 封装了 RequestMappingInfo、HandlerMethod、directUrls、mappingName信息。 */
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
/** 封装 RequestMappingInfo - HandlerMethod 映射关系 */
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
/** 封装 url - RequestMappingInfo 映射信息 */
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
/** 封装 RequestMappingInfo名称 - HandlerMethod列表 映射信息 */
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
/** 封装 handlerMethod - cors跨域配置的映射信息 */
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
/** 读写锁,保证线程安全,在写入的时候不允许读写,读操作可以并行执行 */
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
}
|
封装了许多的有关 url、RequestMappingInfo、HandlerMethod、cors配置等的映射关系,以map的方式存储到成员变量中。
HandlerMethod 的构造及数据结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public class HandlerMethod {
/** Logger that is available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
/** bean实例 */
private final Object bean;
/** beanFactory 工厂 */
@Nullable
private final BeanFactory beanFactory;
/** bean的类型 */
private final Class<?> beanType;
/** 方法 */
private final Method method;
/** 桥接方法 */
private final Method bridgedMethod;
/** 方法参数封装 */
private final MethodParameter[] parameters;
// 省略其他变量...
public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
// 省略无关代码...
// 这里的变量 bean,仅仅封装了一个 beanName,并没有设置具体的实例。这个实例会在第一次调用controller方法时,去设置。
this.bean = beanName;
this.beanFactory = beanFactory;
Class<?> beanType = beanFactory.getType(beanName);
if (beanType == null) {
throw new IllegalStateException("Cannot resolve bean type for bean with name '" + beanName + "'");
}
// 这里仅仅设置了一个beanType,这时候,bean实例并没有封装进来。在真正调用方法执行时,这个bean实例是必须有的。
// 它在别的地方进行了设置。
this.beanType = ClassUtils.getUserClass(beanType);
this.method = method;
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
this.parameters = initMethodParameters();
evaluateResponseStatus();
}
}
|
注意这里的变量 this.bean 保存的是 beanName,而非 bean 的实例。
在构造 HandlerMethod 时,仅仅把 beanName 和 beanClass 设置到成员变量保存起来,在这里并没有获取 bean 的具体实例,这个实例实际上是在第一次调用的时候,通过 beanFactory.getBean() 获取的,获取后,将 this.bean 的值替换为了具体的实例。这也是懒加载的一种体现。
2 RequestMappingHandlerAdapter 的初始化
2.1 数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
public static final MethodFilter INIT_BINDER_METHODS = method ->
AnnotatedElementUtils.hasAnnotation(method, InitBinder.class);
public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
(!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) &&
AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class));
/** 自定义的参数解析器,策略模式的运用, HandlerMethodArgumentResolver中提供了两个方法:是否支持解析参数的判断、解析参数方法。*/
@Nullable
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
/** 参数解析聚合,内部封装了所有的HandlerMethodArgumentResolver实例 */
@Nullable
private HandlerMethodArgumentResolverComposite argumentResolvers;
/** initBinder参数解析器 */
@Nullable
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
/** 自定义的返回值处理器 */
@Nullable
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
/** 返回值处理组合,与WebMvcConfigurer组合类设计模式相同。内部封装了所有的HandlerMethodReturnValueHandler */
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
/** 视图解析器 */
@Nullable
private List<ModelAndViewResolver> modelAndViewResolvers;
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
/** 消息转换器 */
private List<HttpMessageConverter<?>> messageConverters;
/** 一些增强类,参数解析、返回值处理类的封装 */
private List<Object> requestResponseBodyAdvice = new ArrayList<>();
// 省略其他变量...
}
|
RequestMappingHandlerAdapter 封装了许多的策略处理,包括 方法参数解析、返回值处理、消息转换器等等。每一种都包含许多的方式去处理,有太多可能情况,所以使用策略模式。
无论是 参数解析、返回值、消息转换都有很多种可能,比如 post表单提交的参数、以流的方式传递的 json 参数,等等。每一种都对应的有相应的处理实现类。
2.2 主流程
首先会调用初始化方法 afterPropertiesSet(),源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
public void afterPropertiesSet() {
// TODO 在第一次执行时,会初始化ControllerAdvice缓存。
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache();
if (this.argumentResolvers == null) {
// TODO 参数解析器,里面注册了很多的参数解析类。实际上,参数的解析是一个十分复杂的过程,它的可能情况太多了。
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
// 将所有的参数解析器封装到 argumentResolvers 中。
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
// initBinder 参数解析器
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
// 方法返回值处理类注册
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
}
|
- 首先缓存异常处理相关类。
- 注册默认的参数解析器设置。这里会注册一系列的参数解析器。
- 注册 initBinder 参数解析器。同上。
- 注册默认的方法返回值处理类。同上。
2.3 初始化 ControllerAdvice 缓存
源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
private void initControllerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
// TODO 全局异常处理的Bean扫描,@ControllerAdvice 注解的bean会被扫描到。
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
AnnotationAwareOrderComparator.sort(adviceBeans);
List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
// 方法过滤器 @RequestMapping && @ModelAttribute 注解扫描
Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
// 封装adviceBean和 @ModelAttribute 注解方法的映射关系。
this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
}
// 方法过滤器 InitBinder 扫描
Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
// 封装 adviceBean 和 binderMethods 的映射关系
this.initBinderAdviceCache.put(adviceBean, binderMethods);
}
if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
// 省略无关代码...
}
}
|
这里重点在注解扫描,源码如下:
1
2
3
4
5
6
7
8
9
|
public class ControllerAdviceBean implements Ordered {
public static List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) {
// 这里是针对Controller层全局异常处理注解支持的扫描。
return Arrays.stream(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, Object.class))
.filter(name -> context.findAnnotationOnBean(name, ControllerAdvice.class) != null)
.map(name -> new ControllerAdviceBean(name, context))
.collect(Collectors.toList());
}
}
|
上面流程中,扫描了容器中所有带有 @ControllerAdvice 注解的 beanName,并封装为 ControllerAdviceBean。ControllerAdviceBean 中封装了 bean实例(刚开始是beanName)、排序、@ControllerAdvice注解信息。
ControllerAdviceBean 数据结构如下:
1
2
3
4
5
6
7
8
9
10
|
public class ControllerAdviceBean implements Ordered {
/** bean实例 */
private final Object bean;
/** beanFactory */
private final BeanFactory beanFactory;
/** 排序,通过@Order注解来设置 */
private final int order;
/** ControllerAdvice 注解中的参数信息封装 */
private final HandlerTypePredicate beanTypePredicate;
}
|
2.4 注册默认参数解析器
getDefaultArgumentResolvers() 源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
// 这里注册了一系列的默认参数解析器,在大多数应用场景下的参数解析,都是可以支持的,一般不需要我们自定义。
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
}
|
注册了许多的参数解析器,实际上,参数的解析十分复杂。
从类名称上大致可以推断出它的作用。
比如 PathVariableMethodArgumentResolver 就是处理 url 中使用占位符接收参数。RequestParamMethodArgumentResolver 处理表单提交的参数。RequestResponseBodyMethodProcessor 处理json参数等。
2.5 注册默认返回值处理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
// 注册了很多返回值处理类,用于处理返回值的一些信息。
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
handlers.add(new StreamingResponseBodyReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice));
handlers.add(new HttpHeadersReturnValueHandler());
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
return handlers;
}
}
|
如上源码,返回值的处理类也有很多。
其他的一些策略类的注册,与上面流程类似。