Spring MVC介紹(三)之 Annotation解析以及完整的執(zhí)行流程
工作中對(duì)于Spring MVC我們最常用的還是使用注解的方式,那么對(duì)于注解Spring MVC的如何處理的?
<context:component-scan base-package="com.demo.spring.mvc.control" />
<mvc:annotation-driven/>
一、annotation-driven
在前面的介紹中,我們知道了HandlerMapping以及HandlerAdapter撞芍,那么annotation的是什么?
對(duì)于注解:
<mvc:annotation-driven/>
它對(duì)應(yīng)的handlerMapping則是:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
對(duì)應(yīng)的HandlerAdapter則是:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
對(duì)應(yīng)的Handler則是:
org.springframework.web.method.HandlerMethod
這些沒(méi)有配置在配置文件中,注解是怎么實(shí)現(xiàn)的央碟?
來(lái)看下NamespaceHandler接口:
org.springframework.beans.factory.xml.NamespaceHandler
package org.springframework.beans.factory.xml;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
public interface NamespaceHandler {
void init();
BeanDefinition parse(Element element, ParserContext parserContext);
BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
}
實(shí)現(xiàn)這個(gè)接口,則就可以動(dòng)態(tài)的往ioc容器添加BeanDefinition均函,則就動(dòng)態(tài)的添加了bean亿虽。
那么這個(gè)是在哪實(shí)現(xiàn)的呢?
來(lái)看下spring-webmvc包里面的spring.handlers
org\springframework\spring-webmvc\4.3.8.RELEASE\spring-webmvc-4.3.8.RELEASE.jar!\META-INF\spring.handlers
里面內(nèi)容:
http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
點(diǎn)進(jìn)去看一下 MvcNamespaceHandler 這個(gè)類:
package org.springframework.web.servlet.config;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
public MvcNamespaceHandler() {
}
public void init() {
this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
this.registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
this.registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
this.registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
this.registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
this.registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
this.registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
this.registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
this.registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
this.registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
this.registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());
this.registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
this.registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
this.registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
}
}
此時(shí)我們看到了MvcNamespaceHandler extends NamespaceHandlerSupport:
public class MvcNamespaceHandler extends NamespaceHandlerSupport{...}
NamespaceHandlerSupport implements NamespaceHandler
public abstract class NamespaceHandlerSupport implements NamespaceHandler {}
NamespaceHandler接口就是我們剛剛看到的那個(gè)動(dòng)態(tài)注冊(cè)BeanDefinition的接口苞也。
并且在MvcNamespaceHandler.init() 方法中洛勉,可以看到:
this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
并且 AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {}
其中 BeanDefinitionParser 接口:
public interface BeanDefinitionParser {
BeanDefinition parse(Element element, ParserContext parserContext);
}
在 AnnotationDrivenBeanDefinitionParser.parse() 的實(shí)現(xiàn)方法中,可以看到
RequestMappingHandlerMapping 被注冊(cè)到ioc容器中:
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
同樣的還有RequestMappingHandlerAdapter:
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
所以這就是為什么添加了 <mvc:annotation-driven/> 配置如迟,就能實(shí)現(xiàn)mvc的整個(gè)配置了收毫。
二攻走、MVC完整的執(zhí)行流程
之前我們介紹了MVC的異常處理和攔截器,那么加上這兩部分此再,MVC的執(zhí)行流程如下:
DispatcherServlet ==> 找到下面這些組件(1:n)
HandlerMapping ==> 基于url找到對(duì)應(yīng)的handler (其實(shí)是找到HandlerExecutionChain)
HandlerAdapter ==> 基于handler找到對(duì)應(yīng)的適配器 調(diào)用handler返回ModelAndView
(如果出現(xiàn)了異常)
HandlerExceptionResovler ==> 處理異常 返回errorModelAndView
(如果加入了攔截器)
HandlerInterceptor ==> 處理攔截器
ViewResolver ==> 視圖倉(cāng)庫(kù) ==> 基于viewName找到View => 解析生成Html
其中 DispatcherServlet 中調(diào)用 initStrategies 來(lái)初始化上述組件昔搂。
org.springframework.web.servlet.DispatcherServlet#initStrategies
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
有興趣可以看下這些init方法實(shí)現(xiàn)。