在上一篇博客springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)中我们简单地介绍了获取url和HandlerMethod的过程,接下来我介绍一些url和HandlerMethod对应关系的注册过程。

在AbstractHandlerMethodMapping中当bean被注入到容器后会执行一系列的初始化过程,代码如下:

//容器启动时会运行此方法,完成handlerMethod的注册操作
	@Override
	public void afterPropertiesSet() {
		initHandlerMethods();
	}

进行HandlerMethod的注册操作,简单来说就是从springMVC的容器中获取所有的beanName,注册url和实现方法HandlerMethod的对应关系。

//handlerMethod的注册操作
	protected void initHandlerMethods() {
		if (logger.isDebugEnabled()) {
			logger.debug("Looking for request mappings in application context: " + getApplicationContext());
		}
		//从springMVC容器中获取所有的beanName
		String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
				getApplicationContext().getBeanNamesForType(Object.class));
		//注册从容器中获取的beanName
		for (String name : beanNames) {
			if (!name.startsWith(SCOPED_TARGET_NAME_PREFIX) && isHandler(getApplicationContext().getType(name))) {
				detectHandlerMethods(name);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

根据beanName进行一系列的注册,最终实现是在registerHandlerMethod

protected void detectHandlerMethods(final Object handler) {
		//获取bean实例
		Class<?> handlerType =
				(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());

		// Avoid repeated calls to getMappingForMethod which would rebuild RequestMappingInfo instances
		final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
		final Class<?> userType = ClassUtils.getUserClass(handlerType);

		Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
			@Override
			public boolean matches(Method method) {
				//创建RequestMappingInfo
				T mapping = getMappingForMethod(method, userType);
				if (mapping != null) {
					mappings.put(method, mapping);
					return true;
				}
				else {
					return false;
				}
			}
		});

		for (Method method : methods) {
			registerHandlerMethod(handler, method, mappings.get(method));
		}
	}

registerHandlerMethod的注册操作是将beanName,Method及创建的RequestMappingInfo之间的 关系。

//注册beanName和method及RequestMappingInfo之间的关系,RequestMappingInfo会保存url信息
	@Deprecated
	protected void registerHandlerMethod(Object handler, Method method, T mapping) {
		this.mappingRegistry.register(mapping, handler, method);
	}

getMappingForMethod方法是在子类RequestMappingHandlerMapping中实现的,具体实现就是创建一个RequestMappingInfo

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

	private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
		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);
	}

这样就简单实现了将url和HandlerMethod的对应关系注册到mappingRegistry中。

MappingRegistry中的注册实现如下,并且MappingRegistry定义了几个map结构,用来存储注册信息

	private final Map<T, MappingRegistration<T>> registry = new HashMap<T, MappingRegistration<T>>();

		private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();

		private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>();

		private final Map<String, List<HandlerMethod>> nameLookup =
				new ConcurrentHashMap<String, List<HandlerMethod>>();

		private final Map<HandlerMethod, CorsConfiguration> corsLookup =
				new ConcurrentHashMap<HandlerMethod, CorsConfiguration>();

完成beanName,HandlerMethod及RequestMappingInfo之间的对应关系注册。

//注册beanName和method及RequestMappingInfo之间的关系,RequestMappingInfo中有url信息
		public void register(T mapping, Object handler, Method method) {

			this.readWriteLock.writeLock().lock();
			try {
				//创建HandlerMethod
				HandlerMethod handlerMethod = createHandlerMethod(handler, method);
				assertUniqueMethodMapping(handlerMethod, mapping);

				if (logger.isInfoEnabled()) {
					logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
				}
				//保存url和handlerMethod之间的对应关系
				this.mappingLookup.put(mapping, handlerMethod);
				//保存url和RequestMappingInfo对应关系
				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<T>(mapping, handlerMethod, directUrls, name));
			}
			finally {
				this.readWriteLock.writeLock().unlock();
			}
		}

springMVC源码分析--AbstractHandlerMethodMapping注册url和HandlerMethod对应关系(十一)的更多相关文章

  1. springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)

    在之前的博客springMVC源码分析--AbstractHandlerMapping(二)中我们介绍了AbstractHandlerMethodMapping的父类AbstractHandlerMa ...

  2. springmvc 源码分析(一)-- DisparcherServlet的创建和注册到tomcat

    一. servlet 3.0 的使用 1.1 环境搭建: servlet跟spring没有任何关系,我创建一个servlet可以不依赖spring,现在搭建一个纯的servlet项目,并实现简单的类似 ...

  3. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  4. 框架-springmvc源码分析(一)

    框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...

  5. springMVC源码分析--AbstractDetectingUrlHandlerMapping(五)

    上一篇博客springMVC源码分析--AbstractUrlHandlerMapping(三)中我们介绍了AbstractUrlHandlerMapping,主要介绍了一个handlerMap的ur ...

  6. springMVC源码分析--SimpleUrlHandlerMapping(四)

    上一篇博客springMVC源码分析--AbstractUrlHandlerMapping(三)中我们介绍了AbstractUrlHandlerMapping,主要介绍了一个handlerMap的ur ...

  7. springMVC源码分析--AbstractUrlHandlerMapping(三)

    上一篇博客springMVC源码分析--AbstractHandlerMapping(二)中我们介绍了AbstractHandlerMapping了,接下来我们介绍其子类AbstractUrlHand ...

  8. springMVC源码分析--HandlerMapping(一)

    HandlerMapping的工作就是为每个请求找到合适的请求找到一个处理器handler,其实现机制简单来说就是维持了一个url到Controller关系的Map结构,其提供的实际功能也是根据req ...

  9. [心得体会]SpringMVC源码分析

    1. SpringMVC (1) springmvc 是什么? 前端控制器, 主要控制前端请求分配请求任务到service层获取数据后反馈到springmvc的view层进行包装返回给tomcat, ...

随机推荐

  1. C#之Winform跨线程访问控件

    C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它.此时它将会在内部调用ne ...

  2. 3.如何搭建Appium自动化测试环境

    整个APP自动化环境安装可以参照虫师博客安装 附以下链接: http://www.cnblogs.com/fnng/category/695788.html 下面介绍运用到工作中遇到的一些问题 1.如 ...

  3. ●UVA 10652 Board Wrapping

    题链: https://vjudge.net/problem/UVA-10652 题解: 计算几何,Andrew求凸包, 裸题...(数组开小了,还整了半天...) 代码: #include<c ...

  4. [POJ]1279: Art Gallery

    题目大意:有一个N边形展馆,问展馆内有多少地方可以看到所有墙壁.(N<=1500) 思路:模板题,半平面交求出多边形的核后计算核的面积. #include<cstdio> #incl ...

  5. bzoj 4518: [Sdoi2016]征途

    Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜 ...

  6. Codeforces Round #430 D. Vitya and Strange Lesson

    Today at the lesson Vitya learned a very interesting function - mex. Mex of a sequence of numbers is ...

  7. Amazon新一代云端关系数据库Aurora(上)

    本文由  网易云发布. 在2017年5月芝加哥举办的世界顶级数据库会议SIGMOD/PODS上,作为全球最大的公有云服务提供商,Amazon首次系统的总结 了新一代云端关系数据库Aurora的设计实现 ...

  8. 2017-9-19 c语言预备作业

    题目一: (1)我对邹欣老师博客内容的看法 针对邹欣老师的第一种看法,也就是文中所谈的春蚕与园丁的例子.我认为在大学之前的阶段,师生关系可以如此比喻,因为在中学阶段教师与学生的关系,更多地是一个知识的 ...

  9. Axis2 webservice入门--Webservice的发布与调用

    一.Webservice发布 参考 http://www.cnblogs.com/demingblog/p/3263576.html 二.webservice 调用 部分参考:http://www.c ...

  10. Yii2 获取URL的一些方法

    1. 获取url中的host信息: 例如:http://www.nongxiange.com/product/2.html Yii::$app->request->getHostInfo( ...