以 Spring MVC 啟動(dòng) Servlet 為例幻工,其應(yīng)用上下文為 ServletWebServerApplicationContext唉堪,繼承了 GenericWebApplicationContext 的大部分方法槽袄,主要重寫了 postProcessBeanFactory()芹关、refresh()皿桑、onRefresh()撒会、finishRefresh()嘹朗、onClose() 方法。
啟動(dòng)流程
由 refresh() 可知茧彤,重寫方法的執(zhí)行順序?yàn)椋簆ostProcessBeanFactory()骡显、onRefresh()、finishRefresh()曾掂。
1惫谤、postProcessBeanFactory()
- 添加后置處理器 WebApplicationContextServletContextAwareProcessor
- 忽略自動(dòng)裝配以來接口 ServletContextAware
- 注冊(cè) web 應(yīng)用的作用域
2、onRefresh()
- 調(diào)用父類的 onRefresh() 方法
- 創(chuàng)建 Web 服務(wù)器
Spring 容器中會(huì)加載 @Configuration 注解的配置類 ServletWebServerFactoryConfiguration珠洗,它會(huì)按條件注入不同的 web 服務(wù)器工廠類:Tomcat/Jetty/Undertow溜歪,默認(rèn)條件下,可以注入 TomcatServletWebServerFactory许蓖, name 為 tomcatServletWebServerFactory蝴猪。
onRefresh() 創(chuàng)建 Web 服務(wù)器時(shí),首先從 BeanFactory 獲取 ServletWebServerFactory 類型的 Bean膊爪,即上述的 TomcatServletWebServerFactory自阱。利用這個(gè)工廠類的方法public WebServer getWebServer(ServletContextInitializer... initializers)
來創(chuàng)建 TomcatWebServer,這個(gè)方法主要就是為 TomcatWebServer 創(chuàng)建 Tomcat 實(shí)例米酬。此外沛豌,注意其入?yún)?ServletContextInitializer 是函數(shù)式接口,可以將其方法作為參數(shù)傳入赃额,初始化 TomcatWebServer 時(shí)加派,調(diào)用 Tomcat.start() 啟動(dòng) Server,以異步的方式執(zhí)行該函數(shù)接口的實(shí)現(xiàn)類跳芳,即執(zhí)行 onStartup() 方法芍锦。
創(chuàng)建 Tomcat 實(shí)例,是和 Tomcat 啟動(dòng)相關(guān)的內(nèi)容飞盆,也就是創(chuàng)建 Tomcat 相關(guān)的組件的過程娄琉,比如 Server次乓、Service、Connector车胡、Engine檬输、Host、Context匈棘、Wrapper 、Lifecycle 等組件析命。
Tomcat 將在這一步完成初始化的工作主卫,其生命周期狀態(tài)變化為:NEW
->INITIALIZING
->INITIALIZED
,INITIALIZED
表示已經(jīng)初始化的狀態(tài)鹃愤。
3簇搅、finishBeanFactoryInitialization(beanFactory)
從 BeanFactory 獲取 name 為 requestMappingHandlerMapping 的 Bean,并初始化這個(gè) Bean软吐,過程中執(zhí)行其實(shí)現(xiàn)的接口方法 InitializingBean.afterPropertiesSet()瘩将,該方法遍歷所有可用的 Bean,找到 @Controller 或者 @RequestMapping 注解的類凹耙,利用反射技術(shù)姿现,遍歷出這些類的方法及其請(qǐng)求 URL 的映射關(guān)系進(jìn)行緩存。
4肖抱、finishRefresh()
真正完成啟動(dòng) Tomcat备典,其生命周期狀態(tài)變化為:INITIALIZED
->STARTING_PREP
->STARTING
->STARTED
,即表示啟動(dòng)成功意述。
請(qǐng)求流程
Tomcat 接收請(qǐng)求
- 瀏覽器輸入http://127.0.0.1:8080/test提佣,地址127.0.0.1、端口號(hào)8080的 Endpoint 接收到請(qǐng)求荤崇,并將請(qǐng)求交給處理器 Processor 處理拌屏;
- 處理器將請(qǐng)求通過適配器 CoyoteAdapter,從緩存 Mapper 中找到路徑映射术荤,從而依次找到 Engine->Host->Context->Wrapper
- 先調(diào)用過濾器鏈 FilterChain倚喂,過濾之后,執(zhí)行 Servlet
- 執(zhí)行完畢喜每,再將響應(yīng) Response 依次返回
DispatcherServlet
Tomcat 作為 Servlet 容器务唐,負(fù)責(zé)監(jiān)聽 Socket 請(qǐng)求,并將請(qǐng)求映射带兜、并轉(zhuǎn)交給具體的 Servlet 進(jìn)行處理枫笛。Spring MVC 中非常重要的,負(fù)責(zé)請(qǐng)求處理調(diào)度的類 DispatcherServlet刚照,就是 Servlet 的一個(gè)實(shí)現(xiàn)刑巧,所以在 Spring MVC 應(yīng)用中,是使用 DispatcherServlet 來處理請(qǐng)求的,其實(shí)現(xiàn) Servlet 的繼承關(guān)系如下圖:
DispatcherServlet 獲取到請(qǐng)求后的執(zhí)行流程