spring通过在web.xml中配置ContextLoaderListener来加载spring context配置文件和在DispatcherServlet中也可以来加载spring context配置文件,有什么区别?

ContextLoaderListener与DispatcherServlet所加载的applicationContext的区别:

ContextLoaderListener和DispatcherServlet都会在Web容器启动的时候加载一下bean配置. 区别在于:

  • DispatcherServlet一般会加载MVC相关的bean配置管理(如: ViewResolver, Controller, MultipartResolver, ExceptionHandler, etc.)
  • ContextLoaderListener一般会加载整个Spring容器相关的bean配置管理(如: Log, Service, Dao, PropertiesLoader, DataSource Bean, etc.)

spring-root-context.xml与dispatcher-servlet.xml是有点像全局和私有的关系。

spring载入的dispatcher-servlet.xml是隶属于此Servlet的(所以spring可以配置多个分别拥有各自环境的DispatcherServlet),因此其他servlet无法获取到该Context。这一现象在buffalo配置时曾经出现(无法找到服务bean)。
分析了buffalo和spring的源码后,将xml在ContextLoaderListener配置才得以解决。

ContextLoaderListener中加载的spring-root-context.xml成功后,spring 将 applicationContext存放在ServletContext中key值为"org.springframework.web.context.WebApplicationContext.ROOT"的attribute中。(servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context));

可以通过WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)或WebApplicationContextUtils.getWebApplicationContext(servletContext)方法来获取对应的applicationContext。

DispatcherServlet加载的context成功后,如果 publishContext属性的值设置为true的话(缺省为true) 会将applicationContext存放在org.springframework.web.servlet.FrameworkServlet.CONTEXT. + (servletName)的attribute中。
则对应的applicationContext的attribute key值为org.springframework.web.servlet.FrameworkServlet.CONTEXT.mvcServlet。

在每次request请求时,DispatcherServlet会将此applicationContext存放在request中attribute值为org.springframework.web.servlet.DispatcherServlet.CONTEXT中(request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());)。
可以通过 RequestContextUtils.getWebApplicationContext 或WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)方法来获取对应的applicationContext。

从上面的分析可以看出,DispatcherServlet所加载的applicationContext可以认为是mvc私有的context,由于保存在servletContext中的key值与通过ContextLoaderListener加载进来的applicationContext使用的key值不相同,
因此如果只使用DispatcherServlet加载context的话,如果程序中有地方使用WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 来试图获取applicationContext时,就会抛出"No WebApplicationContext found: no ContextLoaderListener registered?"的exception。

最简单的配置web.xml:将所有spring配置文件都让ContextLoaderListener加载,这样就避免了一些奇怪的问题。

 

 

参考:https://ishare.iask.sina.com.cn/f/iFu3kAiDaq.html

 

posted @ 2020-12-15 15:32  MsencSir  阅读(286)  评论(0编辑  收藏  举报