GenericServlet#init(ServletConfig)
中,而後調用this#init()
方法,此處的this指向是DispatcherServlet
對象public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); }
DispatcherServlet
對象執行init()
方法,DispatcherServlet
對象中的這個方法是繼承自HttpServletBean
,此時會進入到HttpServletBean#init
中,這裏面的重點是initServletBean()
方法,調用對應的子類進行初始化public final void init() throws ServletException { // Set bean properties from init parameters. PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } //...忽略 } // Let subclasses do whatever initialization they like. 讓子類進行對應的初始化 initServletBean(); }
FrameworkServlet#initServletBean
中,核心是initWebApplicationContext
和initFrameworkServlet
方法protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'"); try { // this.webApplicationContext = initWebApplicationContext(); // initFrameworkServlet(); } catch (ServletException | RuntimeException ex) { logger.error("Context initialization failed", ex); throw ex; } //log.. }
initWebApplicationContext
方法,對web項目上下文進行初始化protected WebApplicationContext initWebApplicationContext() { //首先得到父容器 WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); //什麼子容器 WebApplicationContext wac = null; //創建父子容器關係 if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } //查找web容器的引用是否存在, 並建立好空ioc容器 if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id wac = findWebApplicationContext(); } //給建好的IOC容器賦值 if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); } //觸發刷新方法 if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. synchronized (this.onRefreshMonitor) { onRefresh(wac); } } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }
DispatcherServlet
的onRefresh
,在onRefresh
中又調用了initStrategies
方法,初始化SpringMVC的九大組件@Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } /** * Initialize the strategy objects that this servlet uses. * <p>May be overridden in subclasses in order to initialize further strategy objects. */ protected void initStrategies(ApplicationContext context) { //多文件上傳組件 initMultipartResolver(context); //本地語言環境 initLocaleResolver(context); //模板處理器 initThemeResolver(context); //HandlerMapping initHandlerMappings(context); //適配器 initHandlerAdapters(context); //異常攔截器 initHandlerExceptionResolvers(context); //視圖預處理器 initRequestToViewNameTranslator(context); //視圖轉換器 initViewResolvers(context); //FlashMap initFlashMapManager(context); }
HandlerMapping
根據request找到相應的處理器。由於Handler(Controller)有兩種形式,一種是基於類的Handler,另外一種是基於Method的Handler(也就是咱們經常使用的)css
HandlerAdapter
調用Handler的適配器。若是把Handler(Controller)當作工具的話,那麼HandlerAdapter就至關於幹活的工人java
HandlerExceptionResolver
對異常的處理web
ViewResolver
用來將String類型的視圖名和Locale解析爲View類型的視圖app
RequestToViewNameTranslator
有的Handler(Controller)處理完後沒有設置返回類型,好比是void方法,這是就須要從request中獲取viewNameide
LocaleResolver
從request中解析出Locale。Locale表示一個區域,好比zh-cn,對不一樣的區域的用戶,顯示不一樣的結果,這就是i18n(SpringMVC中有具體的攔截器LocaleChangeInterceptor)工具
ThemeResolver
主題解析,這種相似於咱們手機更換主題,不一樣的UI,css等ui
MultipartResolver
處理上傳請求,將普通的request封裝成MultipartHttpServletRequestthis
FlashMapManager
用於管理FlashMap,FlashMap用於在redirect重定向中傳遞參數spa