当前位置: 代码迷 >> 综合 >> Spring 注解面面通 之 @RequestMapping 注册处理方法源码解析
  详细解决方案

Spring 注解面面通 之 @RequestMapping 注册处理方法源码解析

热度:7   发布时间:2024-01-17 00:59:20.0

??@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构建配置,设置到RequestMappingHandlerMappingconfig属性中。

??② 设置configurlPathHelperpathMatchersuffixPatternMatchtrailingSlashMatchristeredSuffixPatternMatchcontentNegotiationManager属性。

??③ 调用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

??⑥ 从处理器中查找处理方法,并注册到AbstractHandlerMethodMappingmappingRegistry属性中。

/*** 扫描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()方法。

??① 获取处理器handlerBean类型。

??② 遍历处理器handler的方法,收集符合条件的方法到methods.

??③ 遍历符合条件的方法,将其转换并注册到AbstractHandlerMethodMappingmappingRegistry属性中。

/*** 从处理器中查找处理方法,并注册到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(...)方法。

??主要负责将给定handlermethodmapping注册到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版本源码。

??若文中存在错误和不足,欢迎指正!

  相关解决方案