spring源码---mvc:AbstractHandlerMethodMapping

    他是使用也比较频繁,和@RequestMapping()对应,将一个method变成一个Handlermethod。

1.字段:

初看比较简单:

private boolean detectHandlerMethodsInAncestorContexts = false;
@Nullable
private HandlerMethodMappingNamingStrategy<T> namingStrategy;
private final MappingRegistry mappingRegistry = new MappingRegistry();

其实第三个MappingResigtry是一个内部类,里面放了很多容器:

private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

他的任务就是注册。

2.getHandlerInternal()

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
   String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    //上锁
   this.mappingRegistry.acquireReadLock();
   try {
      HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
      return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
   }
   finally { //解锁
      this.mappingRegistry.releaseReadLock();
   }
}

重点方法lookupHandlerMethod()

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
   List<Match> matches = new ArrayList<>();
   //直接获取
   List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
   if (directPathMatches != null) {
        //1.添加,从directPathMatches添加到 matches中
      addMatchingMappings(directPathMatches, matches, request);
   }
   if (matches.isEmpty()) { //说明directPathMatches为空, 添加所有Method
      addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
   }

   if (!matches.isEmpty()) { //对所有的method方法排序
      Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
      matches.sort(comparator);
    //返回第一个
      Match bestMatch = matches.get(0);
      if (matches.size() > 1) {
         if (CorsUtils.isPreFlightRequest(request)) {
            return PREFLIGHT_AMBIGUOUS_MATCH;
         }
         Match secondBestMatch = matches.get(1);
         if (comparator.compare(bestMatch, secondBestMatch) == 0) {
            Method m1 = bestMatch.handlerMethod.getMethod();
            Method m2 = secondBestMatch.handlerMethod.getMethod();
            throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
                  request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
         }
      }
      request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
      handleMatch(bestMatch.mapping, lookupPath, request);
      return bestMatch.handlerMethod;
   }
   else {
      return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
   }
}

2.1addMatchingMapping()

    这里新出现了Match类,他也是内部类

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
   for (T mapping : mappings) {
      T match = getMatchingMapping(mapping, request);
      if (match != null) { 
         matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
      }
   }
}
private class Match {
   private final T mapping;
   private final HandlerMethod handlerMethod;
...
}

2.2 HandlerMethod类

public class HandlerMethod {
   private final Object bean;
   @Nullable
   private final BeanFactory beanFactory;
   private final Class<?> beanType;
   private final Method method;
   private final Method bridgedMethod;
   private final MethodParameter[] parameters;
   @Nullable
   private HttpStatus responseStatus;
   @Nullable
   private String responseStatusReason;
   @Nullable
   private HandlerMethod resolvedFromHandlerMethod;
...
}

方法构成,主要是构造方法,get方法,不存在set,字段的值在构造方法中已经定下了,对于method来说,重要的是他的参数,所以还有一个类名字为:MethodParameter类,用来存放参数信息。

3.registerHandlerMethod()

    AbstractHandlerMethodMapping初始化的时候, 会调用afterPropertiesSet()方法,进而调用handler查找方法:initHandlerMethods()

public void afterPropertiesSet() {
   initHandlerMethods();
}
protected void initHandlerMethods() {
   String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
         BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
         obtainApplicationContext().getBeanNamesForType(Object.class));

   for (String beanName : beanNames) {
      if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
         Class<?> beanType = null;
         try {
            beanType = obtainApplicationContext().getType(beanName);
         }
         if (beanType != null && isHandler(beanType)) {
            detectHandlerMethods(beanName);  //[重点】
         }
      }
   }
   handlerMethodsInitialized(getHandlerMethods());
}

该方法,直接从容器中,获取所有的beanName,然后进行遍历,获取bean的类型,如果是一个Handler类型的bean(@Controller),那么就处理里面的方法。

isHandler()方法,位于RequestMappingHandlerMapping类(AbstractHandlerMethodMapping的子2类)中:

protected boolean isHandler(Class<?> beanType) {
   return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
         AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

detectHandlerMethods()方法:

protected void detectHandlerMethods(Object handler) {
   //根据beanName Class对象
   Class<?> handlerType = (handler instanceof String ?
         obtainApplicationContext().getType((String) handler) : handler.getClass());

   if (handlerType != null) {
      Class<?> userType = ClassUtils.getUserClass(handlerType);
      Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
            (MethodIntrospector.MetadataLookup<T>) method -> {
               try {
                  return getMappingForMethod(method, userType); //创建
               }
            });
      methods.forEach((method, mapping) -> {
         Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
         registerHandlerMethod(handler, invocableMethod, mapping); //【注册】
      });
   }
}

首先是创建RequestMappingInfo ,该方法位于RequestMappingHandlerMapping类中:

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;
}

    继续创建:

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();
}

注册:registerHandlerMethod()方法

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
   this.mappingRegistry.register(mapping, handler, method);
}

调用内部类进行注册

public void register(T mapping, Object handler, Method method) {
   this.readWriteLock.writeLock().lock(); //上锁
   try {
      HandlerMethod handlerMethod = createHandlerMethod(handler, method); //创建handlerMethod
      assertUniqueMethodMapping(handlerMethod, mapping);
      this.mappingLookup.put(mapping, handlerMethod); //先放入

      List<String> directUrls = getDirectUrls(mapping);
      for (String url : directUrls) {
         this.urlLookup.add(url, mapping);
      }

      String name = null;
      if (getNamingStrategy() != null) {
         name = getNamingStrategy().getName(handlerMethod, mapping);
         addMappingName(name, handlerMethod);
      }

      CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
      if (corsConfig != null) {
         this.corsLookup.put(handlerMethod, corsConfig);
      }

      this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
   }
   finally {
      this.readWriteLock.writeLock().unlock();
   }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值