javascript
Spring-SpringMVC父子容器
轉載自??Spring-SpringMVC父子容器
前言
Spring&SpringMVC作為bean管理容器和MVC默認框架,是大多數web應用都會選擇的方案。在其使用過程中,盡管基于xml的配置bean管理的方式依然存在,但在很多情況下已經采用的強大的注解功能將其替代。實際項目中,Spring和SpringMVC同時配置,以及xml配置bean和注解的混合使用,會造成諸如bean重復加載、多次實例化、無法自動注入、配置不生效等奇怪的異常現象。其實,以上問題的大多數原因還是出在Spring容器的理解與使用上。
?
容器
Spring整體框架核心概念中,容器是核心思想,但在一個項目,容器不一定只有一個,Spring中可以包括多個容器,且容器間存在上下層框架。最常見的使用場景就是同時使用Spring和SpringMVC兩個框架,Srping為父(根)容器,SpringMVC作為子容器。通常的使用過程中,Spring父容器對SpringMVC子容器中的bean是不可見的,而子容器對父容器的中bean卻是可見的,這是這兩種容器的默認規則。但是:
子容器對父容器中內容可見,不是默認規則
?
加載過程
web容器
對于一個web應用,需要將其部署在web容器中,web容器為其提供一個全局的ServletContext,并作為之后Spring容器提供宿主環境。
Spring根容器
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value> </context-param> <listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>1.web.xml中的contextLoaderListener在web容器啟動時,會監聽到web容器的初始化事件,其contextInitialized方法會被調用,在這個方法中,spring會初始化一個啟動上下文作為根上下文,即WebApplicationContext。WebApplicationContext只是接口類,其實際的實現類是XmlWebApplicationContext。
2.此上下文即作為Spring根容器,其對應的bean定義的配置由web.xml中的context-param中的contextConfigLocation指定。根容器初始化完畢后,Spring以
WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE為屬性Key,將其存儲到ServletContext中,便于獲取。
SpringMVC子容器
<servlet><servlet-name>XXXX</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc.xml</param-value></init-param><load-on-startup>1</load-on-startup> </servlet> 1.contextLoaderListener監聽器初始化完畢后,開始初始化web.xml中配置的Servlet,servlet可以配置多個,加載順序按照load-on-startup來執行。以最常見的DispatcherServlet為例,該servlet實際上是一個標準的前端控制器,用以轉發、匹配、處理每個servlet請求。DispatcherServlet上下文在初始化的時候會建立自己的上下文,用以持有SpringMVC相關的bean。2.之后先通過
WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先從ServletContext中獲取之前的根上下文(即WebApplicationContext)作為自己上下文的父上下文,然后建立DispatcherServlet自己的上下文。這個DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,內容包括初始化處理器映射、視圖解析等。該servlet自己持有的上下文默認實現類也是WebApplicationContext。
3.初始化完畢后,spring以與servlet的名字相關(此處并非簡單以servlet名為Key,通過轉換碼生存)的屬性為屬性Key,也將其存到ServletContext中,以便后續使用。這樣每個servlet就持有自己的上下文,即擁有自己獨立的bean空間,同時各個servlet共享相同的根上下文中持有的bean。
當然,在根容器創建與子容器創建之間,還會創建監聽器、過濾器等,完整的加載順序為:
ServletContext?->?context-param?->?listener->?filter?->?servlet由以上過程,即確定了一個bean的使用范圍(該使用范圍,是比bean的scope定義的singleton、prototype、request、session、global-session的五種作用域更上層的內容)。
?
容器布局
容器布局的根本是確定bean的使用范圍。就Spring與SpringMVC布局,也大致分為了兩種方向:
傳統型
父容器:保存數據源、服務層、DAO層、事務的bean。
子容器:保存MVC相關的controller的bean。
概述:事務控制在服務層。由于父容器不能訪問文容器中內容,事務的bean在父容器中,無法訪問子容器中內容,就無法對子容器中controller進行AOP(事務),不過做為傳統型方案,也沒有必要這要做。
激進型
父容器:不關我事~
子容器:管理所有bean。
概述:不使用listener監聽器來加載spring的配置文件,只使用DispatcherServlet來加載Spring的配置,不使用父容器,只使用一個DispatcherServlet,拋棄層次概念。
場景:在增刪改查為主業務的系統里,Dao層接口,Dao層實現類,Service層接口,Service層實現類,Action父類,Action。再加上眾多的O(vo\po\bo)和jsp頁面,在滿足分層的前提下,做一些相對較小功能時會變得非常冗余,所以“激進型”方案就出現了,沒有接口、沒有Service層、可以沒有眾多的O(vo\po\bo),所有事務控制上升到controller層。
關于布局選擇嗎,引用一句很合景的總結:
大項目求穩,小項目求快。
總結
以上是生活随笔為你收集整理的Spring-SpringMVC父子容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qq红包伪装怎么画
- 下一篇: 想要玩转实现负载均衡,你知道这些吗?