Spring MVC相關面試題就是無底洞,反正我是怕了

面試官:在基於Spring框架的Web應用中,Spring的應用上下文配置文件applicationgContext.xml是如何自動加載的?

小小白:當運行一個Web項目時,應用服務器(JBoss、Tomcat等)首先會讀取項目源碼路徑中的web.xml文件,解析其中的配置,發現配置了ContextLoaderListener,因此會執行ContextLoaderListener類中的contextInitialized方法,在這個方法中會調用initWebApplicationContext()方法,根據方法名可以看出這個方法是用於初始化一個WebApplicationContext,簡單理解就是初始化一個Web應用下的Spring容器。在initWebApplicationContext()方法後續代碼實現的內部會根據web.xml中配置的contextConfigLocation屬性加載指定的applicationContext.xml文件,根據這個文件初始化Spring容器。

面試官:如果在web.xml中沒有配置contextConfigLocation參數,是不是就不能加載applicationgContext.xml文件?

小小白:如果沒有配置contextConfigLocation參數,那麼應用啓動時會默認查找應用根目錄下/WEB-INF/applicationContext.xml文件,也就是說這是一個默認加載的文件路徑。

面試官:這個Web應用下的WebApplicationContext初始化完成後,它和ServletContext有什麼關係呢?

小小白:在initWebApplicationContext方法的內部會把初始化後的context存到ServletContext中,具體的就是存到了一個Map類型的屬性中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,value是具體的WebApplicationContext實例對象。

面試官:如果想在代碼中通過ServletContext獲取這個WebApplicationContext,如何操作?

小小白:Spring框架提供了一個WebApplicationContextUtils工具類,通過這個工具類的getWebApplicationContext方法可以獲取到。

面試官:剛剛說到ServletContext,它到底做什麼用的?

小小白:ServletContext定義了一些方法方便Servlet和Servlet容器進行通訊,在一個web應用中所有的Servlet都公用一個ServletContext,Spring在和web應用結合使用的時候,是將Spring的容器存到ServletContext中的,通俗的說就是將一個ApplicationContext存儲到ServletContext的一個Map屬性中。

面試官:有了解過web.xml中listener、filter和servlet的初始化順序嗎?

小小白:首先,對使用<listener>標籤聲明的監聽器類進行實例化,調用監聽器類實例對象的contextInitialized()方法,初始化應用上下文數據;接着對使用<filter>標籤聲明的過濾器類進行實例化,調用過濾器類實例對象的init()方法;如果<servlet>標籤內使用了<load-on-startup>標籤,則按照數值從小到大的順序對Servlet進行實例化,並調用對應的init()方法。

面試官:說到servlet,Spring MVC中的DispatcherServlet有了解過嗎?

小小白:DispatcherServlet是SpringMVC的核心分發器,它實現了請求分發,是處理請求的入口。

面試官:那你說一下它的實現原理?

小小白:DispatcherServlet是一個Servlet,在應用啓動時,DispatcherServlet初始化會執行init方法,查看源碼發現DispatcherServlet的init方法繼承自HttpServletBean,在這個初始化方法中會實例化一個WebApplicationContext對象,並且將初始化後的context存到ServletContext中,讓Servlet和Spring容器進行關聯。在DispatcherServlet的onRefresh方法中,初始化各種請求處理策略,例如文件上傳處理策略、URL請求處理策略、視圖映射處理策略、異常處理策略等,這些策略的大部分執行邏輯都是先從WebApplicationContext中查找,找不到的情況下再加載和DispatcherServlet同目錄下的DispatcherServlet.properties中的各個策略,例如初始化HandlerMapping,註冊各種請求的處理策略及處理類。

面試官:具體說一下DispatcherServlet請求分發的實現原理?

小小白:首先,SpringMVC框架在啓動的時候會遍歷Spring容器中的所有bean,對標註了@Controller或@RequestMapping註解的類中方法進行遍歷,將類和方法上的@RequestMapping註解值進行合併,使用@RequestMapping註解的相關參數值(如value、method等)封裝一個RequestMappingInfo,將這個Controller實例、方法及方法參數信息(類型、註解等)封裝到HandlerMethod中,然後以RequestMappingInfo爲key,HandlerMethod爲value存到一個以Map爲結構的handlerMethods中。

接着,將@RequestMapping註解中的value(即請求路徑)值取出,即url,然後以url爲key,以RequestMappingInfo爲value,存到一個以Map爲結構的urlMap屬性中。

客戶端發起請求的時候,根據請求的URL到urlMap中查找,找到RequestMappingInfo,然後根據RequestMappingInfo到handlerMethods中查找,找到對應的HandlerMethod,接着將HandlerMethod封裝到HandlerExecutionChain;接着遍歷容器中所有HandlerAdapter實現類,找到支持這次請求的HandlerAdapter,如RequestMappingHandlerAdapter,然後執行SpringMVC攔截器的前置方法(preHandle方法),然後對請求參數解析及轉換,然後(使用反射)調用具體Controller的對應方法返回一個ModelAndView對象,執行攔截器的後置方法(postHandle方法),然後對返回的結果進行處理,最後執行afterCompletion方法。 


推薦閱讀

說實話,面試這麼問Spring框架的問題,我快扛不住了

沒使用加號拼接字符串,面試官竟然問我爲什麼

面試官一步一步的套路你,爲什麼SimpleDateFormat不是線程安全的

都說ThreadLocal被面試官問爛了,可爲什麼面試官還是喜歡繼續問

Java註解是如何玩轉的,面試官和我聊了半個小時

如何去除代碼中的多次if而引發的一連串面試問題

三分鐘快速搞定git常規使用

String引發的提問,我差點跪了

就寫了一行代碼,被問了這麼多問題

面試官:JVM對鎖進行了優化,都優化了啥?

synchronized連環問

點點"在看" 唄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章