Spring MVC介紹(三)之 Annotation解析以及完整的執(zhí)行流程

spring.png

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)。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末输拇,一起剝皮案震驚了整個(gè)濱河市摘符,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌策吠,老刑警劉巖逛裤,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異奴曙,居然都是意外死亡别凹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門洽糟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)炉菲,“玉大人,你說(shuō)我怎么就攤上這事坤溃∨乃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵薪介,是天一觀的道長(zhǎng)祠饺。 經(jīng)常有香客問(wèn)我,道長(zhǎng)汁政,這世上最難降的妖魔是什么道偷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮记劈,結(jié)果婚禮上勺鸦,老公的妹妹穿的比我還像新娘。我一直安慰自己目木,他們只是感情好换途,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著刽射,像睡著了一般军拟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上誓禁,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天懈息,我揣著相機(jī)與錄音,去河邊找鬼摹恰。 笑死漓拾,一個(gè)胖子當(dāng)著我的面吹牛阁最,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骇两,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼速种,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了低千?” 一聲冷哼從身側(cè)響起配阵,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎示血,沒(méi)想到半個(gè)月后棋傍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡难审,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年瘫拣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片告喊。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡麸拄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出黔姜,到底是詐尸還是另有隱情拢切,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布秆吵,位于F島的核電站淮椰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纳寂。R本人自食惡果不足惜主穗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毙芜。 院中可真熱鬧忽媒,春花似錦、人聲如沸爷肝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)灯抛。三九已至,卻和暖如春音瓷,著一層夾襖步出監(jiān)牢的瞬間对嚼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工绳慎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纵竖,地道東北人漠烧。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像靡砌,于是被迫代替她去往敵國(guó)和親已脓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容