spring mvc HanderMapping源码

Posted antball

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring mvc HanderMapping源码相关的知识,希望对你有一定的参考价值。

https://my.oschina.net/zhangxufeng/blog/2177464

RequestMappingHandlerMapping getMappingForMethod



	/**
	 * {@inheritDoc} 
	 * Expects a handler to have a type-level @{@link Controller} annotation.
	 */
	@Override
	protected boolean isHandler(Class<?> beanType) {
		return AnnotationUtils.findAnnotation(beanType, Controller.class) != null;
	}


	/**
	 * Uses method and type-level @{@link RequestMapping} annotations to create
	 * the RequestMappingInfo.
	 * 
	 * @return the created RequestMappingInfo, or {@code null} if the method
	 * does not have a {@code @RequestMapping} annotation.
	 * 
	 * @see #getCustomMethodCondition(Method)
	 * @see #getCustomTypeCondition(Class)
	 */
        @Override
	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		RequestMappingInfo info = null;
		RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
		if (methodAnnotation != null) {
			RequestCondition<?> methodCondition = getCustomMethodCondition(method);
			info = createRequestMappingInfo(methodAnnotation, methodCondition);
			RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
			if (typeAnnotation != null) {
				RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
				info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
			}
		}
		return info;
	}

AbstractHandlerMethodMapping


        /**
	 * ApplicationContext initialization and handler method detection.
	 */
	@Override
	public void initApplicationContext() throws ApplicationContextException {
		super.initApplicationContext();
		initHandlerMethods();
	}

	/**
	 * Scan beans in the ApplicationContext, detect and register handler methods.
	 * @see #isHandler(Class)
	 * @see #getMappingForMethod(Method, Class)
	 * @see #handlerMethodsInitialized(Map)
	 */
	protected void initHandlerMethods() {
		if (logger.isDebugEnabled()) {
			logger.debug("Looking for request mappings in application context: " + getApplicationContext());
		}
		
		String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
				getApplicationContext().getBeanNamesForType(Object.class));

		for (String beanName : beanNames) {
                        // 判断类上面是否有Controller 注解 如果有则查找它及它的方法是否有RequestMapping注解
			if (isHandler(getApplicationContext().getType(beanName))){
				detectHandlerMethods(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

	/**
	 * Look for handler methods in a handler.
	 * @param handler the bean name of a handler or a handler instance
	 */
	protected void detectHandlerMethods(final Object handler) {
		Class<?> handlerType = (handler instanceof String) ? 
				getApplicationContext().getType((String) handler) : handler.getClass();

		final Class<?> userType = ClassUtils.getUserClass(handlerType);
				
                //把此类的方法里有RequestMapping注解的方法都找出来
		Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
			public boolean matches(Method method) {
				return getMappingForMethod(method, userType) != null;
			}
		});
		
                //将有RequestMapping注解的方法注册一下  handlerMethods  urlMap     RequestMappingInfo mapping 
		for (Method method : methods) {
			T mapping = getMappingForMethod(method, userType);
			registerHandlerMethod(handler, method, mapping);
		}
	}



	/**
	 * Provide the mapping for a handler method. A method for which no 
	 * mapping can be provided is not a handler method.
	 *
	 * @param method the method to provide a mapping for
	 * @param handlerType the handler type, possibly a sub-type of the method\'s
	 * declaring class
	 * @return the mapping, or {@code null} if the method is not mapped
	 */
	protected abstract T getMappingForMethod(Method method, Class<?> handlerType);


        /**
	 * Register a handler method and its unique mapping.
	 * 
	 * @param handler the bean name of the handler or the handler instance
	 * @param method the method to register
	 * @param mapping the mapping conditions associated with the handler method        RequestMappingInfo mapping 
	 * @throws IllegalStateException if another method was already registered 
	 * under the same mapping
	 */
	protected void registerHandlerMethod(Object handler, Method method, T mapping) {
		HandlerMethod handlerMethod;
		if (handler instanceof String) {
			String beanName = (String) handler;
			handlerMethod = new HandlerMethod(beanName, getApplicationContext(), method);
		}
		else {
			handlerMethod = new HandlerMethod(handler, method);
		}
		
		HandlerMethod oldHandlerMethod = handlerMethods.get(mapping);
		if (oldHandlerMethod != null && !oldHandlerMethod.equals(handlerMethod)) {
			throw new IllegalStateException("Ambiguous mapping found. Cannot map \'" + handlerMethod.getBean()
					+ "\' bean method \\n" + handlerMethod + "\\nto " + mapping + ": There is already \'"
					+ oldHandlerMethod.getBean() + "\' bean method\\n" + oldHandlerMethod + " mapped.");
		}
		
		handlerMethods.put(mapping, handlerMethod);
		if (logger.isInfoEnabled()) {
			logger.info("Mapped \\"" + mapping + "\\" onto " + handlerMethod);
		}
		
		Set<String> patterns = getMappingPathPatterns(mapping);
		for (String pattern : patterns) {
			if (!getPathMatcher().isPattern(pattern)) {
				urlMap.add(pattern, mapping);
			}
		}
	}

RequestMappingInfoHandlerMapping


	/**
	 * Get the URL path patterns associated with this {@link RequestMappingInfo}.
	 */
	@Override
	protected Set<String> getMappingPathPatterns(RequestMappingInfo info) {
		return info.getPatternsCondition().getPatterns();
	}

以上是关于spring mvc HanderMapping源码的主要内容,如果未能解决你的问题,请参考以下文章

spring mvc源码长按ctrl键为啥不跳转

Spring MVC

spring用到的设计模式

spring用到的设计模式

spring用到的设计模式

spring用到的设计模式