ContextLoaderListener 在 Spring 中的角色/目的?

我正在学习 Spring 框架,这是在我的项目中使用。我在 Xml文件中找到了 < em > ContextLoaderListener 条目。但是不能弄清楚它到底如何帮助一个开发人员?

< em > ContextLoaderListener 的官方文档中,它说它将启动 WebApplicationContext。关于这个问题,JavaDocs 说:

接口为 Web 应用程序提供配置。


但是,我不能理解我是什么实现与 ContextLoaderListener内部初始化的 WebApplicationContext

根据我的理解 ContextLoaderListener读取 Spring 配置文件(根据 Xml中的 contextConfigLocation 给出值) ,解析它并加载该配置文件中定义的 单子豆。类似地,当我们想加载 豆子原型时,我们将使用相同的 Web 应用程序上下文来加载它。因此,我们使用 ContextLoaderListener初始化 webapplication,这样我们就可以提前读取/解析/验证配置文件,并且无论何时我们想要注入依赖项,我们都可以立即执行,没有任何延迟。这个理解正确吗?

151386 次浏览

它将为您提供一个挂钩点,以便将您希望在 Web 应用程序部署时执行的一些代码放入其中

你的理解是正确的。我想知道为什么在 ContextLoaderListener 中看不到任何优势。例如,您需要构建一个会话工厂(以管理数据库)。这个操作可能需要一些时间,所以最好在启动时进行。当然,您可以使用 init servlet 或其他方法进行配置,但 Spring 方法的优点是不需要编写代码就可以进行配置。

你的理解是正确的。ApplicationContext是你的春豆生活的地方。ContextLoaderListener的目的有两个:

  1. ApplicationContext的生命周期与 ServletContext的生命周期联系起来

  2. 来自动创建 ApplicationContext,所以你不需要写明确的代码来创建它-这是一个方便的函数。

关于 ContextLoaderListener的另一个方便之处是,它创建了一个 WebApplicationContext,并通过 ServletContextAware bean 和 getServletContext方法提供对 ServletContext的访问。

ContextLoaderListener可以选择。这里只是说明一点: 您可以启动 Spring 应用程序,而无需配置 ContextLoaderListener,这只是 DispatcherServlet最基本的 web.xml

下面是它看起来的样子:

Xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5">
<display-name>Some Minimal Webapp</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>


<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>


<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

创建一个名为 dispatcher-servlet.xml的文件并将其存储在 WEB-INF下。因为我们在欢迎列表中提到了 index.jsp,所以在 WEB-INF下添加这个文件。

Patcher-servlet. xml

dispatcher-servlet.xml中定义 bean:

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">


<bean id="bean1">
...
</bean>
<bean id="bean2">
...
</bean>


<context:component-scan base-package="com.example" />
<!-- Import your other configuration files too -->
<import resource="other-configs.xml"/>
<import resource="some-other-config.xml"/>


<!-- View Resolver -->
<bean
id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property
name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

如果我们编写没有 ContextLoaderListener 的 web.xml,那么我们就不能在春季安全中使用 customAuthenticationProvider 进行通信。因为 DispatcherServlet 是 ContextLoaderListener 的子上下文,customAuthenticationProvider 是 ContextLoaderListener 的 ParentContext 的一部分。因此,父上下文不能具有子上下文的依赖关系。因此,最佳实践是在 contextparam 中编写 spring-context.xml,而不是在 initparam 中编写。

博客“ ContextLoaderListener-Spring MVC 的目的”给出了一个很好的解释。

根据它,Application-Context 是分层的,因此 DispatcherSerlvet 的上下文成为 ContextLoaderListener 上下文的子上下文。因此,在控制器层(Struts 或 Spring MVC)中使用的技术可以独立于根上下文创建的 ContextLoaderListener。

我相信它的真正用途是当您希望拥有多个配置文件或者使用 Xyz.xml文件而不是 applicationcontext.xml 时,例如

< context-param > < param-name > contextConfigLocation < param-value >/WEB-INF/training-service.xml, /WEB-INF/training-data. xml

ContextLoaderListener 的另一种方法是使用 ContextLoaderServlet,如下所示

< servlet > < servlet-name > context < servlet-class > org.springframework.web.context. ContextLoaderServlet < 加载启动 > 1

侦听器类——侦听事件(例如,服务器启动/关闭)

ContextLoaderListener-

  1. 在服务器启动/关闭期间监听
  2. 接受 Spring 配置文件作为输入,根据配置创建 bean 并使其就绪(在关闭期间销毁 bean)
  3. 在 web.xml 中可以这样提供配置文件

    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    

对于一个简单的 Spring 应用程序,您不必在 web.xml中定义 ContextLoaderListener; 您只需将所有 Spring 配置文件放在 <servlet>中:

<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-core-config.xml, classpath:spring/business-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

对于定义了多个 DispatcherServlet的更复杂的 Spring 应用程序,您可以使用由 ContextLoaderListener中定义的所有 DispatcherServlet共享的公共 Spring 配置文件:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/common-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<servlet>
<servlet-name>mvc1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc1-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>


<servlet>
<servlet-name>mvc2</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc2-config.xmll</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

请记住,ContextLoaderListener执行 应用程序上下文的实际初始化工作。

我发现这篇文章很有帮助: Spring MVC-应用程序上下文与 Web 应用程序上下文

当你想把你的 Servlet 文件放在你的自定义位置或自定义名称,而不是默认的变数命名原则 [servletname]-servlet.xml和路径下的 Web-INF/,那么你可以使用 ContextLoaderListener

ContextLoaderListner 是一个 Servlet 侦听器,它将所有不同的配置文件(服务层配置、持久层配置等)加载到单个 Spring 应用程序上下文中。

这有助于跨多个 XML 文件分割 Spring 配置。

一旦加载了上下文文件,Spring 就会基于 bean 定义创建一个 WebApplicationContext 对象,并将其存储在 Web 应用程序的 ServletContext 中。

基本上,您可以使用 ContextLoaderListner 隔离您的根应用程序上下文和 Web 应用程序上下文。

用上下文参数映射的配置文件将表现为根应用程序上下文配置。与调度程序 servlet 映射的配置文件的行为将类似于 Web 应用程序上下文。

在任何 Web 应用程序中,我们可能有多个调度程序 servlet,因此有多个 Web 应用程序上下文。

但是在任何 Web 应用程序中,我们可能只有一个与所有 Web 应用程序上下文共享的根应用程序上下文。

我们应该在根应用程序上下文中定义公共服务、实体、方面等。控制器、拦截器等都在相关的 Web 应用上下文中。

一个示例 web.xml 是

<!-- language: xml -->
<web-app>


<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.config.AppConfig</param-value>
</context-param>
<servlet>
<servlet-name>restEntryPoint</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.config.RestConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restEntryPoint</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>webEntryPoint</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.config.WebConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webEntryPoint</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>


</web-app>

这里配置 example.config 类。AppConfig 可用于在根应用程序上下文中配置服务、实体、方面等,这些服务将与所有其他 Web 应用程序上下文共享(例如,这里我们有两个 Web 应用程序上下文配置类 RestConfig 和 WebConfig)

PS: 这里 ContextLoaderListener 是完全可选的。如果我们不在这里的 web.xml 中提到 ContextLoaderListener,AppConfig 将无法工作。在这种情况下,我们需要在 WebConfig 和 RestConfig 中配置所有服务和实体。

在 Spring 框架的上下文中,ContextLoaderListener的目的是加载应用程序中的其他 bean,比如驱动应用程序后端的中间层和数据层组件。

enter image description here这个 Bootstrap 侦听器将启动和关闭 Spring 的 WebApplicationContext。一个 Web 应用程序可以有多个调度器 servlet,并且每个应用程序都有自己的应用程序上下文,包含控制器、视图解析器、处理程序映射等等。但是,您可能希望在根应用程序上下文中使用服务 bean、 DAO bean,并且希望在所有子应用程序上下文中使用(由调度器 servlet 创建的应用程序上下文)。

这个侦听器的第二个用法是当您想要使用 Spring 安全性时。

根上下文和子上下文 在进一步阅读之前,请理解-

Spring 一次可以有多个上下文。其中之一将是根上下文,所有其他上下文将是子上下文。

所有子上下文都可以访问在根上下文中定义的 bean; 但是相反并不是真的。根上下文不能访问子上下文 bean。

应用背景:

Xml 是每个 Web 应用程序的根上下文配置。 Spring 加载 applicationContext.xml 文件并为整个应用程序创建 ApplicationContext。 每个 Web 应用程序只有一个应用程序上下文。 如果没有使用 contextConfigLocation 参数在 web.xml 中显式声明上下文配置文件名,Spring 将在 WEB-INF 文件夹下搜索 applicationContext.xml,如果找不到该文件,则抛出 FileNotFoundException。

ContextLoaderListener 执行根应用程序上下文的实际初始化工作。 读取“ contextConfigLocation”上下文参数并将其值传递给上下文实例,将其解析为可能的多个文件路径,这些路径可以用任意数量的逗号和空格分隔,例如“ WEB-INF/applicationContext1.xml,WEB-INF/applicationContext2.xml”。 ContextLoaderListener 是可选的。这里只是说明一点: 您可以启动 Spring 应用程序,而无需配置 ContextLoaderListener,只需使用 DispatcherServlet 配置最基本的 web.xml 即可。

调度员 Servlet DispatcherServlet 本质上是一个 Servlet (它扩展了 HttpServlet) ,其主要用途是处理与配置的 URL 模式匹配的传入 Web 请求。它接受一个传入的 URI 并找到控制器和视图的正确组合。所以它是前端控制器。

在 Spring 配置中定义 DispatcherServlet 时,使用 contextConfigLocation 属性提供一个包含控制器类、视图映射等条目的 XML 文件。

WebApplicationContext 除了 ApplicationContext 之外,在一个 Web 应用程序中还可以有多个 WebApplicationContext。 简而言之,与单个 WebApplicationContext 关联的每个 DispatcherServlet。 Xxx-servlet.xml 文件特定于 DispatcherServlet,一个 Web 应用程序可以配置多个 DispatcherServlet 来处理请求。 在这样的场景中,每个 DispatcherServlet 将配置一个单独的 xxx-servlet.xml。但是,applicationContext.xml 对于所有 servlet 配置文件都是通用的。 Spring 将默认加载名为“ xxx-servlet”的文件。在 web.xml 中 xxx 是 servlet 名称的 webapps WEB-INF 文件夹中。 如果要更改该文件名的名称或更改位置,请使用 contextConfigLocation 作为参数名添加 initi-param。

二者之间的比较与联系:

ContextLoaderListener 与 DispatcherServlet

ContextLoaderListener 创建根应用程序上下文。 DispatcherServlet 条目为每个 servlet 条目创建一个子应用程序上下文。 子上下文可以访问在根上下文中定义的 bean。 根上下文中的 bean 不能(直接)访问子上下文中的 bean。 所有上下文都添加到 ServletContext。 可以使用 WebApplicationContextUtils 类访问根上下文。

阅读 Spring 文档之后,了解如下:

A)应用程序-上下文是分层的,WebApplicationContext 也是如此。

B) ContextLoaderListener 为 web 应用程序创建一个根 web 应用程序上下文,并将其放在 ServletContext 中。这个上下文可以用来加载和卸载 Spring 管理的 bean,而不管控制器层(Struts 或 Spring MVC)中使用的是什么技术。

C) DispatcherServlet 创建自己的 WebApplicationContext,处理程序/控制器/视图解析器由此上下文管理。

D)当 ContextLoaderListener 与 DispatcherServlet 一起使用时,首先如前所述创建一个根 web 应用程序上下文,并且 DispatcherSerlvet 也创建一个子上下文,并将其附加到根应用程序上下文。请参阅此处的文件。

当我们使用 Spring MVC 并在服务层使用 Spring 时,我们提供了两个应用程序上下文。第一个使用 ContextLoaderListener 配置,另一个使用 DispatcherServlet 配置

通常,您将在 DispatcherServlet 上下文中定义所有与 MVC 相关的 bean (控制器和视图等) ,以及 ContextLoaderListener 在根上下文中定义所有横切 bean,如安全性、事务、服务等。

更多细节请参考以下内容: Https://siddharthnawani.blogspot.com/2019/10/contextloaderlistener-vs.html