??@RequestMapping
源码解析主要分为两个阶段:
??① @RequestMapping
注释的方法扫描注册。
??② 请求匹配@RequestMapping
注释的方法。
??本文针对第①
阶段从源码角度进行解析,关于第②
阶段请参照《Spring 注解面面通 之 @RequestMapping 请求匹配方法源码解析》。
??注意:@RequestMapping
注释方法扫描注册的起点是RequestMappingHandlerMapping.afterPropertiesSet()
。
??<annotation-driven />
配置
??为何要先说<annotation-driven />
配置呢?
??@RequestMapping
注释方法扫描注册,自RequestMappingHandlerMapping.afterPropertiesSet()
开始,RequestMappingHandlerMapping
实现了InitializingBean
接口,重写方法afterPropertiesSet()
。
??RequestMappingHandlerMapping
正是在<annotation-driven />
配置解析时注册到BeanFactory
中。
/*** 解析<annotation-driven />配置.*/
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);XmlReaderContext readerContext = parserContext.getReaderContext();CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);parserContext.pushContainingComponent(compDefinition);// 创建ContentNegotiationManager.RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);// 创建RequestMappingHandlerMapping的Bean定义.RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);handlerMappingDef.setSource(source);handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);// 设置排序序号.handlerMappingDef.getPropertyValues().add("order", 0);// 设置ContentNegotiationManager.handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);// 矩阵变量enable-matrix-variables属性解析.if (element.hasAttribute("enable-matrix-variables")) {
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);}// 调用configurePathMatchingProperties(...)配置RequestMappingHandlerMapping属性.// 处理属性包括:useSuffixPatternMatch、useTrailingSlashMatch、useRegisteredSuffixPatternMatch、urlPathHelper、pathMatcher.configurePathMatchingProperties(handlerMappingDef, element, parserContext);readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);// 设置CORS相关配置.RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);......// 注册RequestMappingHandlerMapping定义.parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));......return null;
}
??@RequestMapping
注释方法扫描注册
??@RequestMapping
注释方法扫描注册流程:
?
??1) RequestMappingHandlerMapping.afterPropertiesSet()
方法。
??① 创建RequestMappingInfo
构建配置,设置到RequestMappingHandlerMapping
的config
属性中。
??② 设置config
的urlPathHelper
、pathMatcher
、suffixPatternMatch
、trailingSlashMatch
、risteredSuffixPatternMatch
、contentNegotiationManager
属性。
??③ 调用AbstractHandlerMethodMapping.afterPropertiesSet()
继续处理。
/*** Bean设置属性后,初始化调用.*/
@Override
public void afterPropertiesSet() {
// 创建RequestMappingInfo构建配置.this.config = new RequestMappingInfo.BuilderConfiguration();// 设置UrlPathHelper.this.config.setUrlPathHelper(getUrlPathHelper());// 设置PathMatcher.this.config.setPathMatcher(getPathMatcher());// 设置SuffixPatternMatch.this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);// 设置TrailingSlashMatch.this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);// 设置RegisteredSuffixPatternMatch.this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);// 设置ContentNegotiationManager.this.config.setContentNegotiationManager(getContentNegotiationManager());// 调用AbstractHandlerMethodMapping.afterPropertiesSet().super.afterPropertiesSet();
}
???2) AbstractHandlerMethodMapping.initHandlerMethods()
方法。
??① 从ApplicationContext
总取得所有以注册的Bean
名称数组。
??② 遍历从ApplicationContext
总取得所有以注册的Bean
名称数组。
??③ 若Bean
的名称以scopedTarget.
开头,不予处理此类Bean
。
??④ 根据当前Bean
名称获取对应的Bean
类型。
??⑤ 若当前Bean
类型不是由@Cotroller
和@RequestMapping
注释,不予处理此类Bean
。
??⑥ 从处理器中查找处理方法,并注册到AbstractHandlerMethodMapping
的mappingRegistry
属性中。
/*** 扫描ApplicationContext中的Bean,检测并注册处理程序方法.*/
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());}// 取得ApplicationContext中注册的所有Bean.String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :obtainApplicationContext().getBeanNamesForType(Object.class));// 遍历ApplicationContext中注册的所有Bean.for (String beanName : beanNames) {
// 不以"scopedTarget."开头.if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null;try {
beanType = obtainApplicationContext().getType(beanName);}catch (Throwable ex) {
// 一个无法解析的bean类型,可能来自一个延迟加载的Bean - 让我们忽略它.if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);}}// beanType对应的Bean包含@Cotroller或@RequestMapping注解.if (beanType != null && isHandler(beanType)) {
// 从处理器中查找处理方法,并注册到mappingRegistry属性中.detectHandlerMethods(beanName);}}}//在检测到所有处理程序方法后调用.handlerMethodsInitialized(getHandlerMethods());
}
??3) RequestMappingHandlerMapping.isHandler(...)
方法。
??① 给定Bean
是否由@Controller
或@RequestMapping
注释。
/*** 判断给定Bean是否包含@Controller或@RequestMapping.*/
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
??4) AbstractHandlerMethodMapping.detectHandlerMethods()
方法。
??① 获取处理器handler
的Bean
类型。
??② 遍历处理器handler
的方法,收集符合条件的方法到methods
.
??③ 遍历符合条件的方法,将其转换并注册到AbstractHandlerMethodMapping
的mappingRegistry
属性中。
/*** 从处理器中查找处理方法,并注册到mappingRegistry属性中.* @param handler 处理程序或处理程序实例的Bean名称.*/
protected void detectHandlerMethods(final Object handler) {
// 获取Bean类型.Class<?> handlerType = (handler instanceof String ?obtainApplicationContext().getType((String) handler) : handler.getClass());if (handlerType != null) {
final Class<?> userType = ClassUtils.getUserClass(handlerType);// 遍历Bean类的方法,收集符合条件的methods.Map<Method, T> methods = MethodIntrospector.selectMethods(userType,(MethodIntrospector.MetadataLookup<T>) method -> {
try {
// 获取映射的方法.return getMappingForMethod(method, userType);}catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +userType.getName() + "]: " + method, ex);}});if (logger.isDebugEnabled()) {
logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);}// 进行符合条件methods的注册.methods.forEach((method, mapping) -> {
// 在目标类型上选择一个调用方法.Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);// 注册HandlerMethod.registerHandlerMethod(handler, invocableMethod, mapping);});}
}
??5) RequestMappingHandlerMapping.getMappingForMethod(...)
方法。
??① 通过createRequestMappingInfo
创建方法级别映射。
??② 通过createRequestMappingInfo
创建类级别映射。
??③ 合并方法级别和类级别createRequestMappingInfo
映射。
/*** 使用方法级别和类型级别RequestMapping注释创建RequestMappingInfo.* @return 创建的RequestMappingInfo,或者null(如果该方法没有@RequestMapping注释).*/
@Override
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
// 解析方法级别映射.RequestMappingInfo info = createRequestMappingInfo(method);if (info != null) {
// 解析类级别映射.RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);if (typeInfo != null) {
// 合并方法和类级别映射.info = typeInfo.combine(info);}}return info;
}
??6) RequestMappingHandlerMapping.createRequestMappingInfo(...)
方法。
??① RequestMappingHandlerMapping.createRequestMappingInfo(...)
存在重载方法。
??② 在处理器方法级别或类级别查找@RequestMapping
注解。
??③ 通过getCustomTypeCondition(...)
加载自定义类级别匹配条件,通过getCustomMethodCondition(...)
加载自定义方法级别匹配条件。
??④ 调用createRequestMappingInfo(...)
重载方法创建映射。
??⑤ 综合@RequestMapping
注解指定条件和③
中自定义条件创建RequestMappingInfo
实例。
/*** 委托给createRequestMappingInfo(RequestMapping, RequestCondition),* 根据提供的annotatedElement是类或方法来提供适当的自定义RequestCondition.*/
@Nullable
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
// 在方法级别或类级别查找@RequestMapping注解.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);
}/*** 从提供的@RequestMapping注解创建RequestMappingInfo,* 它可以是直接声明的注解、元注解,也可以是在注解层次结构中合并注解属性的合成结果.*/
protected RequestMappingInfo createRequestMappingInfo(RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
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();
}
??7) AbstractHandlerMethodMapping.registerHandlerMethod(...)
方法。
??主要负责将给定handler
、method
、mapping
注册到mappingRegistry
属性中。
/*** 注册处理程序方法及其唯一映射.* 在启动时为每个检测到的处理程序方法调用.* @param handler 处理程序或处理程序实例的Bean名称.* @param method 注册的方法.* @param mapping 与处理程序方法关联的映射条件.*/
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
??8) AbstractHandlerMethodMapping.handlerMethodsInitialized()
方法。
??检测所有处理程序方法后调用。
/*** 检测所有处理程序方法后调用.*/
protected void handlerMethodsInitialized(Map<T, HandlerMethod> handlerMethods) {
}
??总结
??本文对@RequestMapping
注册的处理器的映射解析,了解这部分内容有助于更深入的应用@RequestMapping
注解。
??源码解析基于spring-framework-5.0.5.RELEASE
版本源码。
??若文中存在错误和不足,欢迎指正!