您好,登錄后才能下訂單哦!
這篇文章給大家介紹Spring MVC的上下文在Web容器中的啟動是怎樣的,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
Spring IoC
是一個獨立的模塊,并不能直接在Web容器中發揮作用。
所以要在Web容器中使用IoC容器,需要為Spring IoC
設計一個啟動過程,并把IoC容器導入進來
Web容器的啟動過程一方面處理Web容器的啟動,另一方面將IoC容器載入到web環境中并將其初始化
而Spring MVC
是建立在IoC容器的基礎上的,在導入IoC容器后才能建立MVC
在常見的web.xml中需要配置一個DispatcherServlet
類型的servlet和一個ContextLoaderListener
類型的listener
Spring MVC
通過這兩個類在Web容器中建立MVC,并將創建好的容器放到ServletContext
中
ContextLoaderListener
用于實現Spring IoC
的啟動,創建IoC容器作為"根容器"
DispatcherServlet
創建另一個IoC容器,并與根容器搭建雙親容器,完成MVC的建立
ContextLoaderListener
調用方法contextInitialized()
實現IoC容器的啟動
DispatcherServlet
調用父類的init()
方法創建IoC容器和搭建雙親容器,以搭建好的IoC容器為基礎建立MVC
此initWebApplicationContext()
方法的實現在ContextLoaderListener
的父類ContextLoader
中
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { // 如果ServletContext已經存在根容器,說明已經創建過根容器,就不需要再執行下面的流程 if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw ... } try { if (this.context == null) { // 創建容器 this.context = createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; // 如果容器沒有被初始化過就執行以下流程 if (!cwac.isActive()) { if (cwac.getParent() == null) { // Spring5以后此方法直接返回null值 ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } // 執行容器的refresh()方法刷新容器 configureAndRefreshWebApplicationContext(cwac, servletContext); } } // 將容器作為根容器。以指定常量為key,容器為value將其添加到ServletContext中 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { currentContextPerThread.put(ccl, this.context); } return this.context; } catch (Error err) { throw err; } }
init()
—— initServletBean()
—— initWebApplicationContext()
此initWebApplicationContext()
方法的實現在DispatcherServlet
的父類FrameworkServlet
中
protected WebApplicationContext initWebApplicationContext() { // 從ServletContext中獲取根容器 WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; // 默認this.webApplicationContext==null if (this.webApplicationContext != null) { wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { if (cwac.getParent() == null) { // 將根容器作為父容器 cwac.setParent(rootContext); } // 啟動容器 configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { wac = findWebApplicationContext(); } if (wac == null) { // 如果wac還是為null就創建容器,并將根容器設置為父容器 wac = createWebApplicationContext(rootContext); } if (!this.refreshEventReceived) { // 搭建MVC,初始化Spring MVC的九大組件 onRefresh(wac); } // 獲取 由DispatcherServlet創建的容器名,以kv方式放進ServletContext中 if (this.publishContext) { String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) { Class<?> contextClass = getContextClass(); if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw ... } ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setEnvironment(getEnvironment()); // 設置雙親容器 wac.setParent(parent); String configLocation = getContextConfigLocation(); if (configLocation != null) { wac.setConfigLocation(configLocation); } /** 配置并刷新容器 * 在刷新容器時,會為容器創建一個BeanFactory對象。 * 調用DefaultListableBeanFactory的構造方法時會嘗試獲取父容器并將父容器本身或父容器持有的BeanFactory作為此BeanFactory的parentBeanFactory 這個parentBeanFactory會在getBean中被用到(在獲取bean前,先嘗試從父工廠中獲取bean) **/ configureAndRefreshWebApplicationContext(wac); return wac; }
關于Spring MVC的上下文在Web容器中的啟動是怎樣的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。