关于java:Spring中ContextLoaderListener的角色/目的?

Role/Purpose of ContextLoaderListener in Spring?

我正在学习我的项目中使用的Spring框架。我在web.xml文件中找到了ContextLoaderListener条目。但不知道它到底是如何帮助开发人员的?

在ContextLoaderListener的官方文档中,它表示要启动WebApplicationContext。关于WebApplicationContext,JavaDocs说:

Interface to provide configuration for a web application.

但我无法理解使用内部初始化WebApplicationContext的ContextLoaderListener所实现的效果。

根据我的理解,ContextLoaderListener读取Spring配置文件(在web.xml中对ContextConfigLocation给出值),解析它并加载该配置文件中定义的singleton bean。同样,当我们想要加载原型bean时,我们将使用相同的WebApplication上下文来加载它。因此,我们使用ContextLoaderListener初始化WebApplication,这样我们就可以提前读取/分析/验证配置文件,并且每当我们想要注入依赖项时,都可以立即执行,而不会有任何延迟。这种理解正确吗?


你的理解是正确的。你的春豆就生活在江户1号〔0〕上。ContextLoaderListener的目的是双重的:

  • 将EDOCX1的生命周期(0)与EDOCX1的生命周期(3)联系起来,以及

  • 为了自动创建ApplicationContext,所以不必编写显式代码来创建它——这是一个方便的函数。

  • 关于ContextLoaderListener的另一个方便之处是它创建了一个WebApplicationContextWebApplicationContext提供了通过ServletContextAwarebean和getServletContext方法访问ServletContext的权限。


    ContextLoaderListener是可选的。这里要说明一点:您可以在不配置ContextLoaderListener的情况下启动一个Spring应用程序,只需使用DispatcherServlet配置一个基本的最小web.xml

    下面是它的样子:

    Web.XML

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <?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下。

    调度程序-servlet.xml

    dispatcher-servlet.xml中定义bean:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <?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>


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <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>

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <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应用程序上下文


    博客"ContextLoaderListener的目的——SpringMVC"给出了一个很好的解释。

    根据它,应用程序上下文是层次结构的,因此DispatcherSerlvet的上下文成为ContextLoaderListener上下文的子级。因此,在控制器层(Struts或SpringMVC)中使用的技术可以独立于根上下文创建的ContextLoaderListener。


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

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

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


    如果要将servlet文件放在自定义位置或使用自定义名称,而不是默认命名约定[servletname]-servlet.xmlWeb-INF/下的路径,则可以使用ContextLoaderListener


    enter image description here这个引导侦听器用于启动和关闭Spring的根webapplicationContext。因为Web应用程序可以有多个Dispatcher Servlet,每个都有自己的应用程序上下文,其中包含控制器、视图解析器、处理程序映射等,但您可能希望在根应用程序上下文中有服务bean、DAO bean,并希望在所有子应用程序上下文(由Dispatcher Servlet创建的应用程序上下文)中使用。

    此侦听器的第二个用途是在您想要使用Spring安全性时使用。


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

    使用context-param映射的配置文件将表现为根应用程序上下文配置。使用DispatcherServlet映射的配置文件的行为类似于Web应用程序上下文。

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

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

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

    示例web.xml是

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <!-- 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>

    这里,config class example.config.appconfig可用于配置根应用程序上下文中的服务、实体、特性等,这些根应用程序上下文将与所有其他Web应用程序上下文共享(例如,这里我们有两个Web应用程序上下文config classes restconfig和webconfig)

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


    在Web应用程序部署时,它将为您提供一些希望执行的代码的钩子。


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


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

    上下文加载列表生成器-

  • 在服务器启动/关闭期间侦听
  • 以Spring配置文件为输入,根据配置创建bean并准备好(在关闭期间销毁bean)
  • 在web.xml中可以这样提供配置文件

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

  • 我相信它的真正用途是当您想要有多个配置文件,或者您有xyz.xml文件而不是applicationcontext.xml for eg时。

    contextConfigLocation /WEB-INF/training-service.xml,
    /WEB-INF/training-data.xml

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


    context
    org.springframework.web.context.ContextLoaderServlet
    1


    如果我们在没有ContextLoaderListener的情况下编写web.xml,那么我们就不能在Spring安全性中使用CustomAuthenticationProvider提供安装。因为DispatcherServelet是ContextLoaderListener的子上下文,所以CustomAuthenticationProvider是ContextLoaderListener的ParentContext的一部分。因此父上下文不能具有子上下文的依赖项。因此,最好的做法是在contextparam中编写spring-context.xml,而不是在initparam中编写它。


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