本节咱们继续分析HandlerMapping另外一个实现类ReqeustMappingHandlerMapping,该类是咱们平常开发中使用最多的映射器策略,即咱们在开发中使用的注解开发方式,如:@Controller、@RequestMapping等,都使用的是此映射策略。Spring MVC默认支持该策略。app
本系列文章是基于Spring5.0.5RELEASE。cors
类的继承关系,以下图:ide
第一次看到此图可能会感受好复杂,你们别急,学技术就是这样,首先须要静下心,再一个要学会对已掌握知识点作总结、对比、分类,这样才能把全部的知识点串起来,能系统的了解一项技术。源码分析
以上是我我的的一些经验,但愿对别人能有帮助,废话很少说了,咱们来分析下这张图,以前咱们学过了SimpleUrlHandlerMapping和BeanNameUrlHandlerMapping,经过横向对比,咱们发现,他们都继承自AbstractHandlerMapping抽象类,而AbstractHandlerMapping类的主要工做就是初始化拦截器的功能,三者的实现都是同样的。学习
继续分析,咱们发现RequestMappingHandlerMapping增长实现了InitializingBean和EmbeddedVualeResolverAware接口,即增长了以下能力:ui
这两个接口都是Spring自动帮咱们调用其中的方法的。也就是说,RequestMappingHandlerMapping经过这些能力来完成初始化HandlerMapping接口的。this
以上是对RequestMappingHandlerMapping的宏观分析,下面咱们进行内部细节分析。url
1、经过实现ApplicationContextAware接口,完成拦截器相关组件的初始化spa
2、经过实现InitializingBean接口,完成url与处理器方法的映射(url->RequestMappingInfo,RequstMappingInfo->HandlerMehtod)debug
调用RequestMappingHandlerMapping类实现的afterPropertiesSet()方法,经过该方法最终调到其父类的initHandlerMethods()方法,这个方法是完成映射解析工做:
一、获取上下文环境中全部的bean
二、迭代全部的bean,经过isHandler方法判断是不是handler
2.1 调用RequestMappingHandlerMapping.isHandler方法,根据@Controller或@RequestMapping注解判断(“或”关系,任意一个)三、解析出handler中全部须要处理的方法,即标注了@RequestMapping注解的方法,封装在detectHandlerMehtods方法中
3.1 获取到原始的Class<?>
3.2 使用MethodIntrospector.selectMethods方法过滤具体的handler method,经过模板方法模式getMappingForMethod预留给子类
- RequestMappingHandlerMapping.getMappingForMehtod方法,经过方法、类上面@RequestMapping注解生成匹配条件RequestMappingInfo对象
3.3 对过滤到的每一个method进行注册,经过registerHandlerMehtod方法完成
- 经过createHandlerMethod方法建立HandlerMethod对象来封装处理器方法
- 判断匹配条件与处理器是否冲突,即同一个匹配条件只能对应一个处理器方法
- 把匹配条件与处理器方法存入map
- 从匹配条件中解析出url,经过RequestMappingInfoHandlerMapping.getMappingPathPatterns方法实现,以后把url与匹配条件存入另外一个map
四、对HandlerMethod进行初始化,调用handlerMethodsInitialized方法,其内部什么都没作
以上是初始化RequestMappingHandlerMapping的总体流程。
初始化拦截器
// 初始化拦截器,即初始化url须要的拦截器 @Override protected void initApplicationContext() throws BeansException { extendInterceptors(this.interceptors); detectMappedInterceptors(this.adaptedInterceptors); initInterceptors(); }
控制初始化RequestMappingHandlerMapping.initHanderMethods方法总体流程,代码以下:
/** * 在ApplicationContext上下文扫描全部的bean,检测和注册处理器方法(handler method) */ protected void initHandlerMethods() { if (logger.isDebugEnabled()) { logger.debug("Looking for request mappings in application context: " + getApplicationContext()); } // 从上下文中查找全部的bean String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) : obtainApplicationContext().getBeanNamesForType(Object.class)); // 遍历全部的beanName for (String beanName : beanNames) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class<?> beanType = null; try { // 得到bean的类型 beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isDebugEnabled()) { logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex); } } // 判断类是否被@Controller或是@RequestMapping注释 // isHandler方法由子类RequestMappingHandlerMapping去实现 if (beanType != null && isHandler(beanType)) { // 注册url与处理器方法的关系 detectHandlerMethods(beanName); } } } // 空方法 handlerMethodsInitialized(getHandlerMethods()); } /** * 查找处理程序handler中的处理方法 */ protected void detectHandlerMethods(final Object handler) { // 获取handler的类型 Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { // 获取给定类的用户定义类型,一般为给定类的类型,但在cglib生成子类的状况下,返回的是原始类型 final Class<?> userType = ClassUtils.getUserClass(handlerType); // 获取处理器方法map,key是Method,value是匹配条件RequestMappingInfo对象 // map中不包括未被@RequestMapping注解的方法 Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { try { // 调用子类RequestMappingHandlerMapping的getMappingForMethod方法进行处理,即根据RequestMapping注解信息建立匹配条件RequestMappingInfo对象 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); } // 遍历map,得到Method和RequestMappingInfo,注册他们 methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); // 调用本类registerHandlerMethod()方法 registerHandlerMethod(handler, invocableMethod, mapping); }); } } /** * 注册rul和处理器方法的映射关系 */ protected void registerHandlerMethod(Object handler, Method method, T mapping) { // 调用内部类MappingRegistry的register()方法 this.mappingRegistry.register(mapping, handler, method); } /** * 此方法是内部类MappingRegistry的方法 */ public void register(T mapping, Object handler, Method method) { this.readWriteLock.writeLock().lock(); try { // 建立处理器方法HandlerMethod实例,即Controller中的处理方法 HandlerMethod handlerMethod = createHandlerMethod(handler, method); // 判断匹配条件是否重复,即一个@RequestMapping的映射url只能对应一个方法 assertUniqueMethodMapping(handlerMethod, mapping); if (logger.isInfoEnabled()) { logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod); } // 将匹配条件RequestMappingInfo和处理器方法保存到map中 this.mappingLookup.put(mapping, handlerMethod); // 得到url映射路径,将映射路径和匹配条件对象RequestMappingInfo存起来 // 调用本类的getDerectUrls方法 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); } // 将映射注册对象存入map this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name)); } finally { this.readWriteLock.writeLock().unlock(); } } private List<String> getDirectUrls(T mapping) { List<String> urls = new ArrayList<>(1); // 调用子类RequestMappingInfoHandlerMapping.getMappingPathPatterns方法 for (String path : getMappingPathPatterns(mapping)) { if (!getPathMatcher().isPattern(path)) { urls.add(path); } } return urls; }
根据@RequestMapping生成RequestMappingInfo对象,主要代码以下:
/** * 使用方法和类型注解@RequestMapping建立RequestMappingInfo对象 */ @Override @Nullable protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { // 建立方法的RequestMappingInfo RequestMappingInfo info = createRequestMappingInfo(method); if (info != null) { // 建立类的RequestMappingInfo RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); if (typeInfo != null) { // 将方法RequestMappingInfo和类RequestMappingInfo合并,好比Controller类上有@RequestMapping("/demo"),方法的@RequestMapping("/demo1"),结果为"/demo/demo1" info = typeInfo.combine(info); } } return info; } @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)); // 调用createRequestMappingInfo建立匹配条件对象 return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null); } /** * 构造匹配条件对象 */ 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(); }
提供匹配条件RequestMappingInfo的解析处理,涉及的代码以下:
/** * 获取url集合,即@RequestMapping中设置的value或path */ @Override protected Set<String> getMappingPathPatterns(RequestMappingInfo info) { return info.getPatternsCondition().getPatterns(); }
以上即RequestMappingHandlerMapping对象的初始化过程及初始化过程的核心源码。
本文主要分析了RequestMappingHandlerMapping的初始化过程,但愿对你们有帮助。随着学习的深刻,后面有时间在分析下期中涉及的关键bean,好比:RequestMappingInfo、RequestCondition、HandlerMethod等等。你们加油!
最后建立了qq群方便你们交流,可扫描加入,同时也可加我qq:276420284,共同窗习、共同进步,谢谢!