閱讀961 返回首頁    go 阿裏雲 go 技術社區[雲棲]


org.springframework.web.context.ContextLoaderListener

常用Web框架SpringMVC及WebX級聯容器原理探究
一、前言
使用一個東西最好研究下他的原理,因為如果知其然那麼在排查問題時候會很方便,本文則針對常用web框架SpringMVC和集團的WebX框架的容器級聯關係進行探究。

二、SpringMVC級聯容器探究
SpringMvc是目前使用最頻繁的框架,springmvc裏麵經常會使用兩級級聯容器,並且每層容器都各有用途,本節就來探究下這兩層級聯容器如何創建。

2.1 配置
使用過SpringMVC的童鞋都知道,一般我們在web.xml裏麵會配置一個listener和一個dispatcher,其實這就配置了兩個spring IOC容器,並且dispatcher容器的父容器就是listener的容器。
一般在web.xml裏麵配置如下:


org.springframework.web.context.ContextLoaderListener


contextConfigLocation
WEB-INF/applicationContext.xml


springmvc
org.springframework.web.servlet.DispatcherServlet
1

其中ContextLoaderListener會創建一個IOC容器使用XMLWebApplicationContext來管理,來管理contextConfigLocation配置的xml裏麵的bean.
DispatcherServlet也會創建一個IOC容器使用XMLWebApplicationContext管理,默認管理web-info/springmvc-servlet.xml裏麵的Controller bean。

2.2 ContextLoaderListener創建IOC父容器
image.png

如圖屬性創建context,然後從servletContext獲取在web.xml裏麵配置的xml文件路徑,然後調用spring容器的refresh方法刷新容器解析bean定義,然後把創建好的context放入serlvetcontext的全局變量裏麵。

2.3 DispatcherServlet 創建子IOC容器
image.png

如圖在DispatcherServlet的初始化方法中首先從全局變量表裏麵獲取listener創建的context,然後使用該context作為父上下文創建了servlet的context容器,並且設置namespace為springmvc-servlet,這個在查找配置文件時候用到,最後會拚接為springmvc-servlet.xml,最後刷新容器。

2.4 總結
綜合知道一般我們在lisenter創建的父容器裏麵配置bo類用來具體操作業務,在dispatcher子容器裏麵配的Controller類,然後Controller裏麵具體調用bo類來實現業務。

三、WebX級聯容器探究
WebX框架在集團曾紅火一時,雖然現在已經不主推了,但是其使用子容器隔離不同模塊的思想還是很好的 https://www.jianshu.com/p/ff7f5c0ba7db,下麵就來探討下webx是如何創建一父多子級聯容器的,

3.1 webx容器結構
引用webx官方文檔:
screenshot.png

Webx Framework將一個WEB應用分解成多個小應用模塊:app1、app2,當然名字可以任意取。
每個小應用模塊獨享一個Spring Sub Context子容器。兩個子容器之間的beans無法互相注入。
所有小應用模塊共享一個Spring Root Context根容器。根容器中的bean可被注入到子容器的bean中;反之不可以。將一個大的應用分解成若幹個小應用模塊,並使它們的配置文件相對獨立,這是一種很不錯的開發實踐。

3.2 WebX配置結構
image.png

如圖是我的一個webx項目的例子,其中webx-business.xml和webx-comm.xml是兩個模塊分別對應一個sub容器。common下的webx-component.xml是存放每個模塊都需要的bean,webx-business.xml和webx-comm.xml都import了該文件。

另外每個webx-模塊.xml裏麵會配置一個component-beans.xml 裏麵存放該模塊需要的bean這些bean其他模塊是訪問不到的。如何需要配置一些bean需要所以模塊都可以訪問,那麼需要在webx.xml裏麵配置,因為這裏配置的會被放到root容器。

3.3 Root和Sub容器創建
在web項目中引入webx除了需要引入jar包還需要在web.xml配置個listener.

<listener>
    <listener-class>com.alibaba.citrus.webx.context.WebxContextLoaderListener</listener-class>
</listener> 

這個WebxContextLoaderListener類似於SpringMVC中配置的ContextLoaderListener目的就是contextLister主要是創建IOC容器,然後裝載/WEB-INF/webx.xml, /WEB-INF/webx-*.xml,好像啊,原來:
image.png

前者繼承了後者並且重新了兩個方法。

webxlister.png

如圖:首先創建了webx的Root 容器上下文 WebxComponentsContext,對應解析webx.xml配置文件,然後調用refresh方法去解析該配置文件裏麵的bean。下麵單獨列下spring的容器上下文中refresh內流程,也可以參考 https://www.atatech.org/articles/75912
image.png

上麵的refresh會走這個流程,在走這個流程的postProcessBeanFactory階段會調用WebxComponentsLoader的postProcessBeanFactory方法注冊WebxComponentsCreator到Root容器。

然後在invokeBeanFactoryPostProcessors階段調用WebxComponentsCreator的postProcessBeanFactory創建並初始化子模塊,每個模塊使用WebxComponentImpl來標示。

然後在finishRefresh階段會發送Root容器已經刷新OK的事件,會調用WebxComponentsImpl的onApplicationEvent方法。然後會逐個調用子容器的refresh方法根據配置文件webx-*.xml重走一遍流程。

3.4 總結
分析完流程我們回顧下,對於每個模塊下的web層的Rpc類的實例和Screen實例和自己的compoment-beans.xml裏麵的實例是放到自己的模塊容器裏麵的,其他模塊是訪問不到的。對於需要所有模塊都可以訪問的bean則配置到webx.xml裏麵

最後更新:2017-11-14 16:34:30

  上一篇:go  Deploying MEAN Stack on CentOS 7.2
  下一篇:go  《maven實戰》讀書筆記6——maven聚合和繼承