本文學(xué)習(xí)自阿里大牛RunforLove银舱,很完美的講解文章,原文:[RunforLove]
(http://www.cnblogs.com/RunForLove/p/5688731.html)
極力推薦的spring源碼解讀Qデ臁P灾谩矮锈!
通過對(duì)SpringMVC啟動(dòng)過程的深入研究繁疤,期望掌握J(rèn)ava Web容器啟動(dòng)過程;掌握SpringMVC啟動(dòng)過程揣炕;了解SpringMVC的配置文件如何配置趁舀,為什么要這樣配置;掌握SpringMVC是如何工作的祝沸;掌握Spring源碼的設(shè)計(jì)和增強(qiáng)閱讀源碼的技巧矮烹。
目錄
1.Web容器初始化過程
2.SpringMVC中web.xml配置
3.認(rèn)識(shí)ServletContextListener
4.認(rèn)識(shí)ContextLoaderListener
5.DispatcherServlet初始化(HttpServletBean ? FrameworkServlet ? DispatcherServlet)
6.ContextLoaderListener與DispatcherServlet關(guān)系
7.DispatcherServlet的設(shè)計(jì)
8.DispatcherServlet工作原理
一、Web容器初始化過程
上圖展示了web容器初始化的過程罩锐,其官方文檔給出了這樣的描述:
When a web application is deployed into a container, the following steps must be performed, in this order, before the web application begins processing client requests.
Instantiate an instance of each event listener identified by a <listener> element in the deployment descriptor.
For instantiated listener instances that implement ServletContextListener, call the contextInitialized() method.
Instantiate an instance of each filter identified by a <filter> element in the deployment descriptor and call each filter instance's init() method.
Instantiate an instance of each servlet identified by a <servlet> element that includes a <load-on-startup> element in the order defined by the load-on-startup element values, and call each servlet instance's init() method.
二奉狈、SpringMVC中web.xml的配置
上圖是截取的web.xml中的配置,在<listener>標(biāo)簽中定義了spring容器加載器涩惑;在<servlet>標(biāo)簽中定義了spring前端控制器仁期。
上圖是源碼中接口ServletContextListener的定義,可以看到在其注釋中指明:servlet和Filter初始化前和銷毀后竭恬,都會(huì)給實(shí)現(xiàn)了servletContextListener接口的監(jiān)聽器發(fā)出相應(yīng)的通知跛蛋。
上面是類ContextLoadListener的定義,它實(shí)現(xiàn)了上面的servletContextListener痊硕。這里用到了代理模式赊级,簡(jiǎn)單的代理了ContextLoader類。ContextLoadListener類用來創(chuàng)建Spring application context岔绸,并且將application context注冊(cè)到servletContext里面去理逊。
結(jié)合上面的WEB容器啟動(dòng)的過程,以及接口ServletContextListener和類ContextLoadListener盒揉。我們知道:
在 Servlet API中有一個(gè)ServletContextListener接口晋被,它能夠監(jiān)聽ServletContext對(duì)象的生命周期,實(shí)際上就是監(jiān)聽Web應(yīng)用的生命周期刚盈。當(dāng)Servlet容器啟動(dòng)或終止Web應(yīng)用時(shí)羡洛,會(huì)觸發(fā)ServletContextEvent事件,該事件由ServletContextListener來處理藕漱。在ServletContextListener接口中定義了處理ServletContextEvent 事件的兩個(gè)方法contextInitialized()和contextDestroyed()欲侮。
ContextLoaderListener監(jiān)聽器的作用就是啟動(dòng)Web容器時(shí),自動(dòng)裝配ApplicationContext的配置信息谴分。因?yàn)樗鼘?shí)現(xiàn)了ServletContextListener這個(gè)接口锈麸,在web.xml配置了這個(gè)監(jiān)聽器,啟動(dòng)容器時(shí)牺蹄,就會(huì)默認(rèn)執(zhí)行它實(shí)現(xiàn)的方法忘伞。由于在ContextLoaderListener中關(guān)聯(lián)了ContextLoader這個(gè)類,所以整個(gè)加載配置過程由ContextLoader來完成。
上面是initWebApplicationContext的過程氓奈,方法名稱即是其含義翘魄。方法中首先創(chuàng)建了WebApplicationContext,配置并且刷新實(shí)例化整個(gè)SpringApplicationContext中的Bean舀奶。因此暑竟,如果我們的Bean配置出錯(cuò)的話,在容器啟動(dòng)的時(shí)候育勺,會(huì)拋異常出來的但荤。
綜上,ContextLoaderListener類起著至關(guān)重要的作用涧至。它讀取web.xml中配置的context-param中的配置文件腹躁,提前在web容器初始化前準(zhǔn)備業(yè)務(wù)對(duì)應(yīng)的Application context;將創(chuàng)建好的Application context放置于ServletContext中,為springMVC部分的初始化做好準(zhǔn)備南蓬。
三纺非、DispatchServlet初始化
在SpringMVC架構(gòu)中,DispatchServlet負(fù)責(zé)請(qǐng)求分發(fā)赘方,起到控制器的作用烧颖。下面詳細(xì)來解釋說明:
DispatchServlet名如其義,它的本質(zhì)上是一個(gè)Servlet窄陡。從上面圖可以看到炕淮,下層的子類不斷的對(duì)HttpServlet父類進(jìn)行方法擴(kuò)展。
上圖是抽象類HttpServletBean的實(shí)現(xiàn)泳梆,我們知道HttpServlet有兩大核心方法:init()和service()方法鳖悠。HttpServletBean重寫了init()方法,在這部分优妙,我們可以看到其實(shí)現(xiàn)思路:公共的部分統(tǒng)一來實(shí)現(xiàn),變化的部分統(tǒng)一來抽象憎账,交給其子類來實(shí)現(xiàn)套硼,故用了abstract class來修飾類名。此外胞皱,HttpServletBean提供了一個(gè)HttpServlet的抽象實(shí)現(xiàn)邪意,使的Servlet不再關(guān)心init-param部分的賦值,讓servlet更關(guān)注于自身Bean初始化的實(shí)現(xiàn)反砌。
上圖是FrameworkServlet的官方定義雾鬼, 它提供了整合web javabean和spring application context的整合方案。那么它是如何實(shí)現(xiàn)的呢宴树?在源碼中我們可以看到通過執(zhí)行initWebApplicationContext()方法和initFrameworkServlet()方法實(shí)現(xiàn)策菜。
DispatchServlet是HTTP請(qǐng)求的中央調(diào)度處理器,它將web請(qǐng)求轉(zhuǎn)發(fā)給controller層處理,它提供了敏捷的映射和異常處理機(jī)制又憨。DispatchServlet轉(zhuǎn)發(fā)請(qǐng)求的核心代碼在doService()方法中實(shí)現(xiàn)翠霍,詳細(xì)代碼參照?qǐng)D上。
上圖是DispatchServlet類和ContextLoaderListener類的關(guān)系圖蠢莺。首先寒匙,用ContextLoaderListener初始化上下文,接著使用DispatchServlet來初始化WebMVC的上下文躏将。
上圖是DispatchServlet的工作流程圖锄弱,作為HTTP請(qǐng)求的中央控制器,它在SpringMVC中起著分發(fā)請(qǐng)求的作用祸憋。下面總結(jié)了DispatchServlet設(shè)計(jì)的一些特點(diǎn)總結(jié)棵癣。
四、請(qǐng)求流程