在上一篇博客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. 深入浅出理解 TCP/IP 协议 (一)

    文章转自:https://www.cnblogs.com/onepixel/p/7092302.html TCP/IP 协议栈是一系列网络协议的总和,是构成网络通信的核心骨架,它定义了电子设备如何连入 ...

  2. 一、spring的成长之路——代理设计模式

    java常用的设计模式详解: 1.代理模式(JDK的动态代理) [IDept.java] ​ 这是一个简单的就接口,进行数据的更新 package com.itcloud.pattern.proxy; ...

  3. springMvc配置xml使ResponseBody返回Json

    @ResponseBody 在返回的数据不是html标签的页面,而是其他某种格式的数据时(如json.xml等)使用: 不在springMvc中配置json的处理的话,我们通常会在Controller ...

  4. Joomla!3.7.0 Core SQL注入漏洞动态调试草稿

    参考joolma的mvc框架讲解:http://www.360doc.com/content/11/1219/18/1372409_173441270.shtml 从这个页面开始下断点:Joomla_ ...

  5. 【BZOJ 2395】Time is money

    题目大意有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市能够连通,一条边需要的c的费用和t的时间,定义一个方案的权值v=n-1条边的费用和*n-1条边的时间 ...

  6. hdu 5880 AC自动机

    Family View Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  7. 【Halum操作-UVA 11478】

    ·英文题,述大意:      输入有向图一个(什么边的端点啊,边权啊).每次可以选择一个节点和一个整数,然后把这个结点的出边边权加上该整数,入边边权减去该整数,目标:使得所有边的最小值非负且尽量大. ...

  8. 如何在Google上下载高清原图

    在我们学习和生活中常常一些高清图片作为相关的素材,比如制作PPT.写博文.制作视频都需要大量图片.我们常常会在百度上下载一些图片,但是百度上提供的图片存在很多问题:存在水印.清晰度不够等.而Googl ...

  9. 从 vCenter Server 使用的数据库中清除旧数据 (2075138)(转)

    Document Id 2075138 Symptoms 免责声明: 本文为 Purging old data from the database used by VMware vCenter Ser ...

  10. Tomcat,eclipse热部署的三种方式

    热部署是指在你修改项目BUG的时候对JSP或JAVA类进行了修改在不重启WEB服务器前提下能让修改生效.但是对配置文件的修改除外! 怎么说呢?热部署其实用的算少了,热部署怎么说都是个人部署的,大点的公 ...