Spring2.5源码解读 之 基于annotation的Controller实现原理分析(1)

Spring2.5源码解读 之 基于annotation的Controller实现原理分析(1)

网上已有许多关于Spring源码解读的文章,但对于SpringMVC中基于annotation的Controller这一块,目前还没发现有相关源码解读的文章,这几天,一直在研究SpringMVC,小有所获。这里,对Spring中基于annotation的Controller的实现原理作下简单分析,作为以后学习的参考资料,如果有人也对此感兴趣,也欢迎一起研究,交流心得。

快速开始SpringMVC

1、导入核心JAR,有两种导入方式
   * 导入全部JAR:spring.jar
   * 导入最小JAR:spring-core、spring-beans、spring-context、spring-web、spring-webmvc
   第三方依赖JAR:commons-logging.jar
2、配置核心servlet:

Java代码 复制代码
  1. <servlet>   
  2.     <servlet-name>SpringServlet</servlet-name>   
  3.     <servlet-class>   
  4.         org.springframework.web.servlet.DispatcherServlet   
  5.     </servlet-class>   
  6.     <load-on-startup>1</load-on-startup>   
  7. </servlet>   
  8. <servlet-mapping>   
  9.     <servlet-name>SpringServlet</servlet-name>   
  10.     <url-pattern>*.html</url-pattern>   
  11. </servlet-mapping>  
	<servlet>
		<servlet-name>SpringServlet</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>SpringServlet</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>



* 3、配置包扫描列表
  在[servlet-name]-servlet中配置:

Java代码 复制代码
  1. <context:component-scan base-package="com.spring.test" />  
<context:component-scan base-package="com.spring.test" />



将所有基于annotation的handler放在test包下即可。

  相当简洁的配置,体现出了的Sping的强大、灵活,不过估计不会有人这样用Spring,呵呵

源码分析之旅:


SpringMVC的核心是DispatcherServlet,网上已经有对该类的简单分析,见后面参考资料。对于handler扫描、初始化映射关系等,以后有时间再详细解读,这里只是稍微提一下:
DispatcherServlet的初始化:

Java代码 复制代码
  1. protected void initStrategies(ApplicationContext context) {   
  2.     //方法入参为ApplicationContext,可证明在DispatcherServlet初始化之前,IoC容器已经开始工作了   
  3.     initMultipartResolver(context);   
  4.     initLocaleResolver(context);   
  5.     initThemeResolver(context);   
  6.     initHandlerMappings(context);   
  7.     initHandlerAdapters(context);   
  8.     initHandlerExceptionResolvers(context);   
  9.     initRequestToViewNameTranslator(context);   
  10.     initViewResolvers(context);   
  11. }  
	protected void initStrategies(ApplicationContext context) {
		//方法入参为ApplicationContext,可证明在DispatcherServlet初始化之前,IoC容器已经开始工作了
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
	}



该初始方法主要完成两件工作:
* 1、将容器中配置(在applicationContext.xml中定义)的HandlerMapping、LocaleResolver等等初始化
* 2、如果容器中未配置,则使用默认策略,该默认策略定义在DispatcherServlet.properties文件中

这其中有几个比较重要的组件(也称管道)需要初始化,包括HandlerMapping、HandlerAdapter、ViewResolver。
HandlerMapping

我们从DispatcherServlet的doService方法入手:

Java代码 复制代码
  1. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {   
  2.     ...   
  3.     //将WebApplicationContext放在了request中   
  4.     request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());   
  5.     request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);   
  6.     request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);   
  7.     request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());   
  8.   
  9.     try {   
  10.         doDispatch(request, response);   
  11.     }   
  12.     ...   
  13. }  
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		...
		//将WebApplicationContext放在了request中
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

		try {
			doDispatch(request, response);
		}
		...
	}



可以看出,对于请求的处理实际上是由doDispatch()完成的,这里只对与annotation相关的部分进行分析:

Java代码 复制代码
  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {   
  2.   
  3.     ...        
  4.     try {   
  5.         ModelAndView mv = null;   
  6.         try {   
  7.             //查找匹配的handler   
  8.             mappedHandler = getHandler(processedRequest, false);   
  9.             if (mappedHandler == null || mappedHandler.getHandler() == null) {   
  10.                 //如果没有,写入404错误   
  11.                 noHandlerFound(processedRequest, response);   
  12.                 return;   
  13.             }   
  14.   
  15.             //调用handler的方法   
  16.             HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());   
  17.             mv = ha.handle(processedRequest, response, mappedHandler.getHandler());   
  18.     ...   
  19.   
  20. }  
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	
		...		
		try {
			ModelAndView mv = null;
			try {
				//查找匹配的handler
				mappedHandler = getHandler(processedRequest, false);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					//如果没有,写入404错误
					noHandlerFound(processedRequest, response);
					return;
				}

				//调用handler的方法
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
		...

	}



再来看查找handler的过程:

Java代码 复制代码
  1. protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {   
  2.     ...   
  3.     //初始时handlerMappings中有两个:   
  4.     //1、BeanNameUrlHandlerMapping:根据bean的名字查找匹配的handler,意味我们可以在容器中将bean名以url定义,如"/order/*"   
  5.     //2、DefaultAnnotationHandlerMapping:根据annotation定义查找   
  6.     //每个handlerMapping中都维持有一个url-handler的HashMap,该列表在生成在初始化时完成   
  7.     Iterator it = this.handlerMappings.iterator();   
  8.     while (it.hasNext()) {   
  9.         HandlerMapping hm = (HandlerMapping) it.next();   
  10.         ...   
  11.         handler = hm.getHandler(request);//实际的匹配过程交由handlerMapping完成   
  12.         ...   
  13.     }   
  14.     return null;   
  15. }  
	protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
		...
		//初始时handlerMappings中有两个:
		//1、BeanNameUrlHandlerMapping:根据bean的名字查找匹配的handler,意味我们可以在容器中将bean名以url定义,如"/order/*"
		//2、DefaultAnnotationHandlerMapping:根据annotation定义查找
		//每个handlerMapping中都维持有一个url-handler的HashMap,该列表在生成在初始化时完成
		Iterator it = this.handlerMappings.iterator();
		while (it.hasNext()) {
			HandlerMapping hm = (HandlerMapping) it.next();
			...
			handler = hm.getHandler(request);//实际的匹配过程交由handlerMapping完成
			...
		}
		return null;
	}



实际查找handler的过程由DefaultAnnotationHandlerMapping类完成。从它的继承层次可以看出,匹配的主要工作都由其父类完成了。在父类中定义了算法的骨架,具体的处理交由子类完成,这是Templet设计模式的典型应用。[[BR]]

先看父类AbstractHandlerMapping中定义的算法骨架:

Java代码 复制代码
  1. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {   
  2.     Object handler = getHandlerInternal(request);//交由子类实现   
  3.     if (handler == null) {   
  4.         handler = getDefaultHandler();   
  5.     }   
  6.     if (handler == null) {   
  7.         return null;   
  8.     }   
  9.   
  10.     if (handler instanceof String) {    //如果handler是String,即完整类名,在容器中定义   
  11.         String handlerName = (String) handler;   
  12.         handler = getApplicationContext().getBean(handlerName);//从IoC中直接获取   
  13.     }   
  14.     return getHandlerExecutionChain(handler, request);   
  15. }  
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		Object handler = getHandlerInternal(request);//交由子类实现
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}

		if (handler instanceof String) {	//如果handler是String,即完整类名,在容器中定义
			String handlerName = (String) handler;
			handler = getApplicationContext().getBean(handlerName);//从IoC中直接获取
		}
		return getHandlerExecutionChain(handler, request);
	}



AbstractHandlerMapping的子类AbstractUrlHandlerMapping中getHandlerInternal的定义:

Java代码 复制代码
  1. protected Object getHandlerInternal(HttpServletRequest request) throws Exception {   
  2.   
  3.     Object handler = lookupHandler(lookupPath, request);   
  4.     if (handler == null) {   
  5.         ...   
  6.     }   
  7.     return handler;   
  8. }   
  9.   
  10. protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {   
  11.     // 直接匹配:   
  12.     Object handler = this.handlerMap.get(urlPath);   
  13.     if (handler != null) {   
  14.         validateHandler(handler, request);//@RequestMapping的其它属性匹配交由子类完成,如method和param的匹配   
  15.         return buildPathExposingHandler(handler, urlPath);   
  16.     }   
  17.     // 正则表达式匹配:   
  18.     String bestPathMatch = null;   
  19.     for (Iterator it = this.handlerMap.keySet().iterator(); it.hasNext();) {   
  20.         String registeredPath = (String) it.next();   
  21.         if (getPathMatcher().match(registeredPath, urlPath) &&   
  22.                 (bestPathMatch == null || bestPathMatch.length() < registeredPath.length())) {   
  23.             bestPathMatch = registeredPath;//可以看出,匹配原则是按照url更长则更匹配   
  24.         }   
  25.     }   
  26.     if (bestPathMatch != null) {   
  27.         handler = this.handlerMap.get(bestPathMatch);   
  28.         validateHandler(handler, request);//@RequestMapping的其它属性匹配交由子类完成,如method和param的匹配   
  29.         String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPathMatch, urlPath);   
  30.         return buildPathExposingHandler(handler, pathWithinMapping);   
  31.     }   
  32.     // No handler found...   
  33.     return null;   
  34. }  
	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {

		Object handler = lookupHandler(lookupPath, request);
		if (handler == null) {
			...
		}
		return handler;
	}

	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
		// 直接匹配:
		Object handler = this.handlerMap.get(urlPath);
		if (handler != null) {
			validateHandler(handler, request);//@RequestMapping的其它属性匹配交由子类完成,如method和param的匹配
			return buildPathExposingHandler(handler, urlPath);
		}
		// 正则表达式匹配:
		String bestPathMatch = null;
		for (Iterator it = this.handlerMap.keySet().iterator(); it.hasNext();) {
			String registeredPath = (String) it.next();
			if (getPathMatcher().match(registeredPath, urlPath) &&
					(bestPathMatch == null || bestPathMatch.length() < registeredPath.length())) {
				bestPathMatch = registeredPath;//可以看出,匹配原则是按照url更长则更匹配
			}
		}
		if (bestPathMatch != null) {
			handler = this.handlerMap.get(bestPathMatch);
			validateHandler(handler, request);//@RequestMapping的其它属性匹配交由子类完成,如method和param的匹配
			String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPathMatch, urlPath);
			return buildPathExposingHandler(handler, pathWithinMapping);
		}
		// No handler found...
		return null;
	}



子类DefaultAnnotationHandlerMapping中@RequestMapping的匹配过程:

Java代码 复制代码
  1. protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {   
  2.     RequestMapping mapping = this.cachedMappings.get(handler.getClass());   
  3.     if (mapping == null) {   
  4.         mapping = AnnotationUtils.findAnnotation(handler.getClass(), RequestMapping.class);   
  5.     }   
  6.     if (mapping != null) {   
  7.         validateMapping(mapping, request);//具体的匹配在validateMapping中完成   
  8.     }   
  9. }   
  10.   
  11. protected void validateMapping(RequestMapping mapping, HttpServletRequest request) throws Exception {   
  12.     RequestMethod[] mappedMethods = mapping.method();   
  13.   
  14.     //请求方法是否匹配?   
  15.     if (!ServletAnnotationMappingUtils.checkRequestMethod(mappedMethods, request)) {   
  16.         String[] supportedMethods = new String[mappedMethods.length];   
  17.         for (int i = 0; i < mappedMethods.length; i++) {   
  18.             supportedMethods[i] = mappedMethods[i].name();   
  19.         }   
  20.         throw new HttpRequestMethodNotSupportedException(request.getMethod(), supportedMethods);//直接就抛异常了?似乎不妥,为什么不尝试下一个比较匹配的那个URL呢?也有可能是父类的算法定义有问题   
  21.     }   
  22.   
  23.     //请求参数是否匹配?   
  24.     String[] mappedParams = mapping.params();   
  25.     if (!ServletAnnotationMappingUtils.checkParameters(mappedParams, request)) {   
  26.         throw new ServletException("Parameter conditions {" +   
  27.                 StringUtils.arrayToDelimitedString(mappedParams, ", ") +   
  28.                 "} not met for request parameters: " + request.getParameterMap());   
  29.     }   
  30. }  
	protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {
		RequestMapping mapping = this.cachedMappings.get(handler.getClass());
		if (mapping == null) {
			mapping = AnnotationUtils.findAnnotation(handler.getClass(), RequestMapping.class);
		}
		if (mapping != null) {
			validateMapping(mapping, request);//具体的匹配在validateMapping中完成
		}
	}

	protected void validateMapping(RequestMapping mapping, HttpServletRequest request) throws Exception {
		RequestMethod[] mappedMethods = mapping.method();

		//请求方法是否匹配?
		if (!ServletAnnotationMappingUtils.checkRequestMethod(mappedMethods, request)) {
			String[] supportedMethods = new String[mappedMethods.length];
			for (int i = 0; i < mappedMethods.length; i++) {
				supportedMethods[i] = mappedMethods[i].name();
			}
			throw new HttpRequestMethodNotSupportedException(request.getMethod(), supportedMethods);//直接就抛异常了?似乎不妥,为什么不尝试下一个比较匹配的那个URL呢?也有可能是父类的算法定义有问题
		}

		//请求参数是否匹配?
		String[] mappedParams = mapping.params();
		if (!ServletAnnotationMappingUtils.checkParameters(mappedParams, request)) {
			throw new ServletException("Parameter conditions {" +
					StringUtils.arrayToDelimitedString(mappedParams, ", ") +
					"} not met for request parameters: " + request.getParameterMap());
		}
	}




请求方法及参数的匹配过程由ServletAnnotationMappingUtils类的静态方法完成,逻辑比较简单:

Java代码 复制代码
  1. public static boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) {   
  2.     if (!ObjectUtils.isEmpty(methods)) {   
  3.         boolean match = false;   
  4.         for (RequestMethod method : methods) {   
  5.             if (method.name().equals(request.getMethod())) {   
  6.                 match = true;   
  7.             }   
  8.         }   
  9.         if (!match) {   
  10.             return false;   
  11.         }   
  12.     }   
  13.     return true;   
  14. }   
  15.   
  16. public static boolean checkParameters(String[] params, HttpServletRequest request) {   
  17.     if (!ObjectUtils.isEmpty(params)) {   
  18.         for (String param : params) {   
  19.             int separator = param.indexOf('=');   
  20.             if (separator == -1) {   
  21.                 if (param.startsWith("!")) {   
  22.                     if (WebUtils.hasSubmitParameter(request, param.substring(1))) {   
  23.                         return false;   
  24.                     }   
  25.                 }   
  26.                 else if (!WebUtils.hasSubmitParameter(request, param)) {   
  27.                     return false;   
  28.                 }   
  29.             }   
  30.             else {   
  31.                 String key = param.substring(0, separator);   
  32.                 String value = param.substring(separator + 1);   
  33.                 if (!value.equals(request.getParameter(key))) {   
  34.                     return false;   
  35.                 }   
  36.             }   
  37.         }   
  38.     }   
  39.     return true;   
  40. }  
	public static boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) {
		if (!ObjectUtils.isEmpty(methods)) {
			boolean match = false;
			for (RequestMethod method : methods) {
				if (method.name().equals(request.getMethod())) {
					match = true;
				}
			}
			if (!match) {
				return false;
			}
		}
		return true;
	}

	public static boolean checkParameters(String[] params, HttpServletRequest request) {
		if (!ObjectUtils.isEmpty(params)) {
			for (String param : params) {
				int separator = param.indexOf('=');
				if (separator == -1) {
					if (param.startsWith("!")) {
						if (WebUtils.hasSubmitParameter(request, param.substring(1))) {
							return false;
						}
					}
					else if (!WebUtils.hasSubmitParameter(request, param)) {
						return false;
					}
				}
				else {
					String key = param.substring(0, separator);
					String value = param.substring(separator + 1);
					if (!value.equals(request.getParameter(key))) {
						return false;
					}
				}
			}
		}
		return true;
	}




至此,handler的匹配过程结束,bean的实例作为匹配的handler返回。可以看出,匹配过程并未深入到方法一级,如果类级别和方法级别都定义了url,在这一层次会忽略方法级别的。其实,spring也不推荐在类级别和方法级别同时定义url。[[BR]]
再回到DispatcherServlet中,找到匹配handler后,下一步就要去调用handler,调用的方式有许多,spring抽像出了一个接口HandlerAdapter,接口的定义:

Java代码 复制代码
  1. public interface HandlerAdapter {   
  2.   
  3.     boolean supports(Object handler); //是否支持此种类型的handler   
  4.   
  5.     ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; //具体的处理过程   
  6.   
  7.     long getLastModified(HttpServletRequest request, Object handler);   
  8. }  
public interface HandlerAdapter {

	boolean supports(Object handler); //是否支持此种类型的handler

	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;	//具体的处理过程

	long getLastModified(HttpServletRequest request, Object handler);
}



DispatcherServlet中寻找合适的HandlerAdapter的过程:

Java代码 复制代码
  1. protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {   
  2.   
  3.     /*  
  4.     spring默认提供四个HandlerAdapter:  
  5.         HttpRequestHandlerAdapter:处理HttpRequestHandler接口的实例  
  6.         SimpleControllerHandlerAdapter:处理Controller接口的实例  
  7.         ThrowawayControllerHandlerAdapter:已经过时  
  8.         AnnotationMethodHandlerAdapter:处理annotation定义的实例  
  9.     */  
  10.     Iterator it = this.handlerAdapters.iterator();   
  11.     while (it.hasNext()) {   
  12.         HandlerAdapter ha = (HandlerAdapter) it.next();   
  13.         if (logger.isDebugEnabled()) {   
  14.             logger.debug("Testing handler adapter [" + ha + "]");   
  15.         }   
  16.         if (ha.supports(handler)) {   
  17.             return ha;   
  18.         }   
  19.     }   
  20.     ...   
  21. }  
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {

		/*
		spring默认提供四个HandlerAdapter:
			HttpRequestHandlerAdapter:处理HttpRequestHandler接口的实例
			SimpleControllerHandlerAdapter:处理Controller接口的实例
			ThrowawayControllerHandlerAdapter:已经过时
			AnnotationMethodHandlerAdapter:处理annotation定义的实例
		*/
		Iterator it = this.handlerAdapters.iterator();
		while (it.hasNext()) {
			HandlerAdapter ha = (HandlerAdapter) it.next();
			if (logger.isDebugEnabled()) {
				logger.debug("Testing handler adapter [" + ha + "]");
			}
			if (ha.supports(handler)) {
				return ha;
			}
		}
		...
	}



基于annotation的handler则是由AnnotationMethodHandlerAdapter进行处理,来看AnnotationMethodHandlerAdapter中相关处理代码:

Java代码 复制代码
  1. //是否支持此类型的handler?   
  2. public boolean supports(Object handler) {   
  3.     return getMethodResolver(handler).hasHandlerMethods();   
  4. }   
  5.   
  6. private ServletHandlerMethodResolver getMethodResolver(Object handler) {   
  7.     Class handlerClass = ClassUtils.getUserClass(handler);   
  8.     ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);   
  9.     if (resolver == null) {   
  10.         resolver = new ServletHandlerMethodResolver(handlerClass);//在父类的构造方法中完成handler的解析   
  11.         this.methodResolverCache.put(handlerClass, resolver);//缓存起来,方法调用时有用   
  12.     }   
  13.     return resolver;   
  14. }   
  15.   
  16. public final boolean hasHandlerMethods() {   
  17.     return !this.handlerMethods.isEmpty();//非常简单的判断,如果该类中的方法标记有@RequestMapping就返回true,也意味着它支持此种类型的handler   
  18. }  
	//是否支持此类型的handler?
	public boolean supports(Object handler) {
		return getMethodResolver(handler).hasHandlerMethods();
	}

	private ServletHandlerMethodResolver getMethodResolver(Object handler) {
		Class handlerClass = ClassUtils.getUserClass(handler);
		ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);
		if (resolver == null) {
			resolver = new ServletHandlerMethodResolver(handlerClass);//在父类的构造方法中完成handler的解析
			this.methodResolverCache.put(handlerClass, resolver);//缓存起来,方法调用时有用
		}
		return resolver;
	}

	public final boolean hasHandlerMethods() {
		return !this.handlerMethods.isEmpty();//非常简单的判断,如果该类中的方法标记有@RequestMapping就返回true,也意味着它支持此种类型的handler
	}



好了,到这里,handler已确定,由谁去处理handler也已确定,剩下的工作就是如何调用了。来看具体的调用代码:

Java代码 复制代码
  1. public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)   
  2.         throws Exception {   
  3.   
  4.     ...   
  5.     if (this.synchronizeOnSession) {   
  6.         HttpSession session = request.getSession(false);   
  7.         if (session != null) {   
  8.             Object mutex = WebUtils.getSessionMutex(session);   
  9.             synchronized (mutex) {   
  10.                 return invokeHandlerMethod(request, response, handler);   
  11.             }   
  12.         }   
  13.     }   
  14.     return invokeHandlerMethod(request, response, handler);   
  15. }   
  16.   
  17. protected ModelAndView invokeHandlerMethod(   
  18.         HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {   
  19.   
  20.     try {   
  21.         ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);//缓存中已有   
  22.         Method handlerMethod = methodResolver.resolveHandlerMethod(request);//确定具体该调用哪个方法   
  23.         ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);   
  24.         ServletWebRequest webRequest = new ServletWebRequest(request, response);   
  25.         ExtendedModelMap implicitModel = new ExtendedModelMap();//方法入参ModelMap的原型   
  26.   
  27.         Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);//调用方法   
  28.         ModelAndView mav =   
  29.                 methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);//构建ModelAndView   
  30.         methodInvoker.updateModelAttributes(   
  31.                 handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);//处理ModelMap中的值   
  32.         return mav;   
  33.     }   
  34.     catch (NoSuchRequestHandlingMethodException ex) {   
  35.         return handleNoSuchRequestHandlingMethod(ex, request, response);   
  36.     }   
  37. }  
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		...
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					return invokeHandlerMethod(request, response, handler);
				}
			}
		}
		return invokeHandlerMethod(request, response, handler);
	}

	protected ModelAndView invokeHandlerMethod(
			HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

		try {
			ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);//缓存中已有
			Method handlerMethod = methodResolver.resolveHandlerMethod(request);//确定具体该调用哪个方法
			ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
			ServletWebRequest webRequest = new ServletWebRequest(request, response);
			ExtendedModelMap implicitModel = new ExtendedModelMap();//方法入参ModelMap的原型

			Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);//调用方法
			ModelAndView mav =
					methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);//构建ModelAndView
			methodInvoker.updateModelAttributes(
					handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);//处理ModelMap中的值
			return mav;
		}
		catch (NoSuchRequestHandlingMethodException ex) {
			return handleNoSuchRequestHandlingMethod(ex, request, response);
		}
	}



其中,确定具体调用哪个方法这个过程比较复杂,由ServletHandlerMethodResolver完成。

Java代码 复制代码
  1. public Method resolveHandlerMethod(HttpServletRequest request) throws ServletException {   
  2.     ...   
  3.     for (Method handlerMethod : getHandlerMethods()) {   
  4.         RequestMappingInfo mappingInfo = new RequestMappingInfo();   
  5.         RequestMapping mapping = AnnotationUtils.findAnnotation(handlerMethod, RequestMapping.class);   
  6.         mappingInfo.paths = mapping.value();   
  7.         //如果类级别没有定义@RequestMapping,则使用方法级别定义的   
  8.         if (!hasTypeLevelMapping() || !Arrays.equals(mapping.method(), getTypeLevelMapping().method())) {   
  9.             mappingInfo.methods = mapping.method();   
  10.         }   
  11.         if (!hasTypeLevelMapping() || !Arrays.equals(mapping.params(), getTypeLevelMapping().params())) {   
  12.             mappingInfo.params = mapping.params();   
  13.         }   
  14.         boolean match = false;   
  15.         if (mappingInfo.paths.length > 0) {//先检查url是否匹配   
  16.             for (String mappedPath : mappingInfo.paths) {   
  17.                 if (isPathMatch(mappedPath, lookupPath)) {   
  18.                     if (checkParameters(mappingInfo, request)) {   
  19.                         match = true;   
  20.                         targetPathMatches.put(mappingInfo, mappedPath);   
  21.                     }   
  22.                     else {   
  23.                         break;   
  24.                     }   
  25.                 }   
  26.             }   
  27.         }   
  28.         else {   
  29.             //如果没有定义url,则只需检查其它项是否匹配,如param、method
rar包内含有spring2.5.6源码,解压即可使用 源代码分析,是一件既痛苦又快乐的事情,看别人写的代码是通过的,但当你能够看明白的时候,相信快乐也会随之而来,为了减少痛苦,更快的带来快乐,在这里希望通过这篇文章对觉得困难的朋友有一个帮助。 本文以spring框架的XmlBeanFactory为入手点进行分析,希望能够以尽量简洁明了的方式给予有需要的朋友一定的帮助。 首先来打开该类的代码,我们将看到如下代码: Java代码 public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } } public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } } 这个类的代码很简单,一个成员对象加两个构造函数,从这里我们可以看出,最重要的地方在于最后一个构造函数: Java代码 super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); 第一句就是将父亲工厂交给父类的构造函数,实际上最后也就是把父工厂保存到类的parentBeanFactory成员对象中,这个对象是在AbstractBeanFactory抽象类中定义的,而这个父工厂也会一直传递到该抽象类进行保存。第二句就是整个类中最重要的地方了,顾名思义,它的目的是通过XmlBeanDefinitionReader这个XML的Reader从资源resource中(也就是你的配置文件)读取bean的定义。接下来我们打开XmlBeanDefinitionReader的loadBeanDefinitions方法,我们可看到在这个方法里代码就一行,调用了一个同名不同参的方法,而参数是EncodedResource的一个实例,这个类实际上是Resource的一个包装类,用来保存资源的Encode的,那接下来我们再看被调用的loadBeanDefinitions方法,这个方法里最主要的部分就是: Java代码 InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 这里的目的是将资源包装成一个InputSource,连同Resource作为参数传递到doLoadBeanDefinitions方法 Java代码 DocumentBuilderFactory factory = createDocumentBuilderFactory(); if (logger.isDebugEnabled()) { logger.debug("Using JAXP implementation [" + factory + "]"); } DocumentBuilder builder = createDocumentBuilder(factory); Document doc = builder.parse(inputSource); return registerBeanDefinitions(doc, resource); DocumentBuilderFactory factory = createDocumentBuilderFactory(); if (logger.isDebugEnabled()) { logger.debug("Using JAXP implementation [" + factory + "]"); } DocumentBuilder builder = createDocumentBuilder(factory); Document doc = builder.parse(inputSource); return registerBeanDefinitions(doc, resource); 这个方法的目的一目了然,就是为了将资源解释成为Document对象,然后调用registerBeanDefinitions方法,这里不做详细解释,不了解的话请去看看关于JAXP的介绍。接下来我们打开registerBeanDefinitions方法: Java代码 public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException { XmlBeanDefinitionParser parser = (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass); return parser.registerBeanDefinitions(this, doc, resource); } public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException { XmlBeanDefinitionParser parser = (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass); return parser.registerBeanDefinitions(this, doc, resource); } 这里创建了一个XmlBeanDefinitionParser接口的实现,这个接口的具体类是DefaultXmlBeanDefinitionParser,这个接口很简单,只有registerBeanDefinitions一个方法,这个方法的作用也很明了,就是用来注册Bean的定义的,所以说类和方法的名字一定要起得有意义,这样可以让人一看就大概了解其作用,减少了很多阅读代码的痛苦。废话不多说,我们打开DefaultXmlBeanDefinitionParser的registerBeanDefinitions方法,这个类就是解释XML配置文件的核心类了,打开registerBeanDefinitions方法后我们看到如下代码: Java代码 public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource) throws BeanDefinitionStoreException { this.beanDefinitionReader = reader; this.resource = resource; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); //初始化根元素 initDefaults(root); if (logger.isDebugEnabled()) { logger.debug("Default lazy init '" + getDefaultLazyInit() + "'"); logger.debug("Default autowire '" + getDefaultAutowire() + "'"); logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'"); } preProcessXml(root);//一个空方法用于扩展 int beanDefinitionCount = parseBeanDefinitions(root);//解释配置的主要方法 if (logger.isDebugEnabled()) { logger.debug("Found " + beanDefinitionCount + " elements in " + resource); } postProcessXml(root); //一个空方法用于扩展 return beanDefinitionCount; } public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource) throws BeanDefinitionStoreException { this.beanDefinitionReader = reader; this.resource = resource; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); //初始化根元素 initDefaults(root); if (logger.isDebugEnabled()) { logger.debug("Default lazy init '" + getDefaultLazyInit() + "'"); logger.debug("Default autowire '" + getDefaultAutowire() + "'"); logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'"); } preProcessXml(root);//一个空方法用于扩展 int beanDefinitionCount = parseBeanDefinitions(root);//解释配置的主要方法 if (logger.isDebugEnabled()) { logger.debug("Found " + beanDefinitionCount + " elements in " + resource); } postProcessXml(root); //一个空方法用于扩展 return beanDefinitionCount; } 在这个方法当中,主要用于解释定义的有两个方法,一个是initDefaults,一个是parseBeanDefinitions,第一个方法是用来解释根元素的属性的,例如lazy-init, autowire等,而parseBeanDefinitions就是用来解释具体的bean定义了,方法代码如下: Java代码 protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException { NodeList nl = root.getChildNodes(); int beanDefinitionCount = 0; for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (IMPORT_ELEMENT.equals(node.getNodeName())) { importBeanDefinitionResource(ele); } else if (ALIAS_ELEMENT.equals(node.getNodeName())) { String name = ele.getAttribute(NAME_ATTRIBUTE); String alias = ele.getAttribute(ALIAS_ATTRIBUTE); this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias); } else if (BEAN_ELEMENT.equals(node.getNodeName())) { beanDefinitionCount++; BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false); BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory()); } } } return beanDefinitionCount; } protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException { NodeList nl = root.getChildNodes(); int beanDefinitionCount = 0; for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (IMPORT_ELEMENT.equals(node.getNodeName())) { importBeanDefinitionResource(ele); } else if (ALIAS_ELEMENT.equals(node.getNodeName())) { String name = ele.getAttribute(NAME_ATTRIBUTE); String alias = ele.getAttribute(ALIAS_ATTRIBUTE); this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias); } else if (BEAN_ELEMENT.equals(node.getNodeName())) { beanDefinitionCount++; BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false); BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory()); } } } return beanDefinitionCount; } 其他标签具体如何被解释这里就不多说,相信大家也能看得懂,这里主要讲一下解释bean的的处理,我们注意以下代码: Java代码 else if (BEAN_ELEMENT.equals(node.getNodeName())) { beanDefinitionCount++; BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false); BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory()); } else if (BEAN_ELEMENT.equals(node.getNodeName())) { beanDefinitionCount++; BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false); BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory()); } 这里是当碰到一个bean标签的时候所进行的处理,也既是对bean的定义进行解释,可以看到parseBeanDefinitionElement方法的第一个参数就是bean则个元素,第二个参数表示该bean是否为内置的bean,从这里进行解释的bean都不可能是内置的,所以这里直接以false为参数,打开parseBeanDefinitionElement方法,就可以看到这个方法里就是对bean的内部的解释,也很简单,也不多讲了,呵呵(下班时间已经到了,所以就写这么多了,基本的流程也就这样,没什么特别难的地方。),对了,最后还有一点就是解释完后,bean的定义将会被保存到beanFactory中,这个beanFactory的实现就是XmlBeanFactory了,该beanFactory是在new的时候被传递到reader中的,就是该类中以下这行代码: Java代码 private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); 好了,就这么多了,本文只作为参考,只讲解了如何加载bean定义这块,只作为一个参考,希望对其他朋友能有所帮助吧,因为时间匆忙,有错漏的地方请指正。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值