`
sha0k
  • 浏览: 84891 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Spring MVC 源码学习札记(四)HandlerMapping和HandlerAdapter(3)

 
阅读更多

上一节主要阅读了BeanNameUrlHandlerMapping类,并理清了它的父类关系,值得注意的是它的爷爷的爸爸也就是AbstractHandlerMapping实现了HandlerMapping接口,而继承了WebApplicationObjectSupport类,在AbstractDetectingUrlHandlerMapping类中,有这样一个方法:

/**
	 * Calls the {@link #detectHandlers()} method in addition to the
	 * superclass's initialization.
	 */
	@Override
	public void initApplicationContext() throws ApplicationContextException {
		super.initApplicationContext();
		detectHandlers();
	}

 上一节没有说明这个,经过我翻WebApplicationObjectSupport类和它的父类ApplicationObjectSupport发现有一个setApplicationContext(ApplicationContext context)方法,在其中调用了initApplicationContext方法,前面的setter肯定是在bean构造时用到的,更上层的以后再去阅读理解吧,到这里就追溯到了handler探测的本源。

 DefaultAnnoationHandlerMapping类也是继承自AbstractDetectingUrlHandlerMapping类,则必然实现了它的抽象方法:

/**
	 * Determine the URLs for the given handler bean.
	 * @param beanName the name of the candidate bean
	 * @return the URLs determined for the bean,
	 * or <code>null</code> or an empty array if none
	 */
	protected abstract String[] determineUrlsForHandler(String beanName);

  那么detectHandler接下来的执行顺序就和上一节的顺序相同,这时我们跳到了DefaultAnnoationHandlerMapping类中的该方法:

/**
	 * Checks for presence of the {@link org.springframework.web.bind.annotation.RequestMapping}
	 * annotation on the handler class and on any of its methods.
	 */
	@Override
	protected String[] determineUrlsForHandler(String beanName) {
		ApplicationContext context = getApplicationContext();
		Class<?> handlerType = context.getType(beanName);
		RequestMapping mapping = context.findAnnotationOnBean(beanName, RequestMapping.class);
		if (mapping != null) {
			// @RequestMapping found at type level
			this.cachedMappings.put(handlerType, mapping);
			Set<String> urls = new LinkedHashSet<String>();
			String[] typeLevelPatterns = mapping.value();
			if (typeLevelPatterns.length > 0) {
				// @RequestMapping specifies paths at type level
				String[] methodLevelPatterns = determineUrlsForHandlerMethods(handlerType);
				for (String typeLevelPattern : typeLevelPatterns) {
					if (!typeLevelPattern.startsWith("/")) {
						typeLevelPattern = "/" + typeLevelPattern;
					}
					for (String methodLevelPattern : methodLevelPatterns) {
						String combinedPattern = getPathMatcher().combine(typeLevelPattern, methodLevelPattern);
						addUrlsForPath(urls, combinedPattern);
					}
					addUrlsForPath(urls, typeLevelPattern);
				}
				return StringUtils.toStringArray(urls);
			}
			else {
				// actual paths specified by @RequestMapping at method level
				return determineUrlsForHandlerMethods(handlerType);
			}
		}
		else if (AnnotationUtils.findAnnotation(handlerType, Controller.class) != null) {
			// @RequestMapping to be introspected at method level
			return determineUrlsForHandlerMethods(handlerType);
		}
		else {
			return null;
		}
	}

 既然是默认注解支持的HandlerMapping,那么它必然是去探测@RequestMapping所注解的Handler和Method。这里就有必要来看看RequestMapping接口的定义:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {

	String[] value() default {};

	RequestMethod[] method() default {};

	String[] params() default {};

	String[] headers() default {}; 

}

 value数组显然是存储所有该Handler中的url,method则是POST GET等方法,RequestMethod是一个enum类型

public enum RequestMethod {

	GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE

}

 context.findAnnotationOnBean(beanName, RequestMapping.class)显然是查找了该Handler上所有使用了@RequestMapping的注解,将它们的value,method取出,再封装到RequestMapping类对象中。接下来的加入缓存语句就不用解释了。

我们来看看determineUrlsForHandlerMethods方法的源码:

/**
	 * Derive URL mappings from the handler's method-level mappings.
	 * @param handlerType the handler type to introspect
	 * @return the array of mapped URLs
	 */
	protected String[] determineUrlsForHandlerMethods(Class<?> handlerType) {
		final Set<String> urls = new LinkedHashSet<String>();
		Class<?>[] handlerTypes =
				Proxy.isProxyClass(handlerType) ? handlerType.getInterfaces() : new Class<?>[]{handlerType};
		for (Class<?> currentHandlerType : handlerTypes) {
			ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
				public void doWith(Method method) {
					RequestMapping mapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
					if (mapping != null) {
						String[] mappedPaths = mapping.value();
						for (String mappedPath : mappedPaths) {
							addUrlsForPath(urls, mappedPath);
						}
					}
				}
			});
		}
		return StringUtils.toStringArray(urls);
	}

 这里就比较麻烦了,先从字面意思理解就是查询类中的方法,找到方法对应的RequestMapping的所包含的value,组成一个url数组。

接下来看它的实现,首先是检查了handlerType是否是一个代理类

/**
     * Returns true if and only if the specified class was dynamically
     * generated to be a proxy class.
*/
public static boolean isProxyClass(Class<?> cl) {
	if (cl == null) {
	    throw new NullPointerException();
	}
       
	return proxyClasses.containsKey(cl);
    }

/** set of all generated proxy classes, for isProxyClass implementation */
    private static Map proxyClasses =
	Collections.synchronizedMap(new WeakHashMap());

 接下来是反射和回调,我也看到云里雾里的。。。。理解不来,以后再想吧,直到它最后是得到的url就行了。

handlerType.getInterfaces();

用于得到所有handlerType实现的接口的Class对象

new Class<?>[]{handlerType}

得到的还只是handlerType的Class对象

所以这里就有些不懂为什么要这么做,希望有高手看到我的文章 帮我解答下疑惑

 

 

 

 

 

 

 

 

 

 

 

 

 

0
0
分享到:
评论

相关推荐

    SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门

    在本篇博客“SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门”中,我们将探讨Spring MVC框架的核心组件——HandlerMapping和HandlerAdapter。这两个组件是Spring MVC处理请求的关键,它们负责映射HTTP...

    Spring MVC源码深度剖析开源架构源码2021.pdf

    Spring MVC是Java EE开发中广泛使用的一个Web框架,它是Spring框架的一部分,主要负责Model-View-Controller(MVC)架构模式的...通过学习和实践,开发者可以更有效地利用Spring MVC框架来构建高性能的Web应用程序。

    开发Spring MVC应用程序补充—程序源码下载.rar_spring_spring mvc_spring mvc 源码_sp

    标题中的"开发Spring MVC应用程序补充—程序源码下载.rar_spring_spring mvc_spring mvc 源码_sp"表明这是一个关于Spring MVC框架的开发教程,其中包含了源代码供学习者参考。Spring MVC是Spring框架的一个核心组件...

    springmvc项目源码

    通过深入学习这个 Spring MVC 项目源码,你可以掌握 MVC 设计模式的运用,了解 Spring 框架的组件协同工作方式,以及在实际项目中的最佳实践。这将有助于提升你的 Java Web 开发技能,更好地理解和使用 Spring MVC。

    spring mvc mybatis 整合源码,带数据库脚本,带详细注释

    - 学习Spring MVC和MyBatis的整合,可以参考官方文档、教程和开源项目的源码。 - 通过调试源码,理解其实现原理,有助于提升实战技能。 总结,这个压缩包提供了一个完整的Spring MVC和MyBatis整合的示例,包含了...

    Spring MVC jar包

    而`spring-framework-2.5.6-with-docs.zip`可能包含了Spring 2.5.6的源码和文档,帮助开发者了解Spring MVC的内部实现和最佳实践。 总之,这个压缩包提供了开发基于Spring MVC和Hibernate的Java Web应用所需要的...

    Spring5MVC源码.docx

    【Spring5MVC源码分析】 Spring MVC 是一个基于Java的、用于构建Web应用程序的、高度可插拔的MVC框架,它是Spring Framework的重要组成部分。Spring MVC的核心目标是简化前端控制器的开发,使得开发者可以专注于...

    精通spring mvc 4 看透springmvc pdf 高清完全版

    本书首先介绍了Spring MVC的基础知识,包括如何搭建Spring MVC环境,以及它的核心组件如DispatcherServlet、ModelAndView、HandlerMapping和HandlerAdapter等的工作原理。这些组件在Web请求处理过程中扮演着重要角色...

    spring mvc 的入门级资料

    在 Spring MVC 中,核心类和接口是 DispatcherServlet、HandlerMapping、HandlerAdapter、Controller、ViewResolver、HandlerInterceptor、View 等。 DispatcherServlet 是 Spring MVC 的前置控制器,它负责处理...

    Spring MVC核心组件之HandlerMapping详解

    ### Spring MVC核心组件之HandlerMapping详解 #### 一、引言 在Java Web开发领域,Spring MVC框架因其灵活且强大的特性而备受青睐。...理解和掌握`HandlerMapping`的工作机制对于深入学习Spring MVC框架至关重要。

    Spring MVC 基础实例源码01

    这个"Spring MVC 基础实例源码01"的资源很可能是为了帮助初学者理解Spring MVC的核心概念和基本用法。下面我们将详细探讨Spring MVC的一些关键知识点。 1. **MVC模式**:MVC(Model-View-Controller)是一种设计...

    spring mvc框架源码

    通过深入研究源码,我们可以更好地理解Spring MVC的运行机制,如何配置和使用其特性,以及如何优化和调试Spring MVC应用。对于开发人员来说,掌握Spring MVC的源码分析有助于提升Web应用开发的效率和质量。

    spring MVC基础学习

    - 创建Spring MVC的配置文件,例如`servlet-context.xml`,配置HandlerMapping、HandlerAdapter、ViewResolver等组件。 - 在配置文件中声明Controller Bean,通常使用注解@Controller。 3. **注解驱动开发**: -...

    Spring MVC 学习记录总结1

    在这个学习记录总结中,我们将深入理解Spring MVC的核心概念、主要组件以及其工作流程。 1. Spring MVC 概述 Spring MVC 是Spring框架的一部分,它基于Spring IoC(Inversion of Control,控制反转)容器,简化了...

    spring mvc与mybatis的集成

    2. **配置 Spring**:在 `applicationContext.xml` 或者 Spring Boot 的配置文件中,配置 Spring MVC 的 DispatcherServlet、HandlerMapping 和 HandlerAdapter。同时,配置 Spring 的 DataSource,这是连接数据库的...

    spring-webmvc-5.0.9 jar包、源码和javadoc

    spring-webmvc-5.0.9.RELEASE-sources.jar则包含了源码,可以深入研究Spring Web MVC的实现细节,对于学习和调试都非常有帮助。 九、依赖管理 在实际项目中,Spring Web MVC往往与其他Spring模块如Core、AOP、Data...

    Spring.MVC学习指南.pdf

    这份“Spring.MVC学习指南.pdf”很可能是为了帮助开发者深入理解和掌握Spring MVC的核心概念、工作原理以及实践技巧。下面将详细阐述Spring MVC的相关知识点。 1. **核心组件**: - **DispatcherServlet**:Spring...

    Spring MVC Helloword代码

    3. **创建Spring MVC配置**:创建一个XML文件(如`servlet-context.xml`),配置HandlerMapping、HandlerAdapter、视图解析器等。 4. **编写Controller**:创建一个名为`GreetingController`的Java类,使用`@...

    Spring MVC简单例子

    8. **配置文件**:理解Spring MVC的配置文件,如`servlet-context.xml`,它定义了Spring MVC的组件,如视图解析器、HandlerMapping和HandlerAdapter等。 9. **Maven或者Gradle构建**:项目可能使用Maven或Gradle...

    spring-mvc-showcase

    此外,该项目还展示了如何配置 Spring MVC,例如在 web.xml 中配置 DispatcherServlet,以及在 Spring 配置文件中定义 HandlerMapping 和 HandlerAdapter 等。这有助于理解 Spring MVC 的工作流程。 "spring-mvc-...

Global site tag (gtag.js) - Google Analytics