【问题标题】:About multiple containers in spring framework关于spring框架中的多个容器
【发布时间】:2013-09-05 20:28:57
【问题描述】:

在典型的 Spring MVC 项目中,有两个“容器”:一个由 ContextLoaderListener 创建,另一个由 DispatchServlet 创建。

我想知道,这真的是两个IoC容器实例吗?(我看到两个bean配置文件,一个是root-context.xml另一个是servlet-context.xml

如果有2个容器,那是什么关系?

在一个容器中声明的 bean 可以在另一个容器中使用吗?

【问题讨论】:

  • 它们不会创建两个不同的容器实例,而是创建两个不同的应用程序上下文。
  • 时隔多年,读到了spring源码。现在,我可以说:1)是的,有两个 ApplicationContext 实例(每个实例将包含一个 beanFactory 的实例) 2)mvc 层的实例是子实例并保留父实例的引用。 3)父实例中的bean可以被子使用,但是子实例中的bean不能被父使用。

标签: spring spring-mvc dependency-injection inversion-of-control


【解决方案1】:

没有创建两个单独的容器。通常,您希望 spring 在需要对象时实例化 servlet-context.xml 中声明的对象。因此,您将 servlet-context.xml 配置文件映射到 Dispatcher Servlet,即您希望在请求到达 Dispatcher Servlet 时初始化对象。

<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

如果您想在加载上下文时初始化对象并执行操作,您可以在部署描述符的context-param 标记中声明配置文件。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>

您可以通过在 servlet-context.xml 和 root-context.xml 中声明单独的 bean,然后在自定义的 Context Loader Listener 类中自动装配它们来测试这一点。你会发现只有 root-context 实例被初始化并且 servlet-context bean 为空。

【讨论】:

    【解决方案2】:

    来自Spring Official Website

    接口org.springframework.context.ApplicationContext 代表 Spring IoC 容器,负责 实例化、配置和组装上述 bean。 容器获取关于要实例化哪些对象的指令, 通过读取配置元数据来配置和组装。这 配置元数据以 XML、Java 注释或 Java 代码。

    再次来自官方文档:

    在 Web MVC 框架中,每个 DispatcherServlet 都有自己的 WebApplicationContext,它继承了所有已经定义在 根 WebApplicationContext。这些继承的 bean 可以 在特定于 servlet 的范围内被覆盖,您可以定义新的 给定 Servlet 实例的本地特定范围的 bean。

    现在来回答您的问题,正如here 所述:

    在 Spring Web Applications 中,有两种类型的容器,每一种 它的配置和初始化方式不同。一个是 “应用程序上下文”,另一个是“Web 应用程序上下文”。 让我们先谈谈“应用程序上下文”。应用程序上下文 是由 ContextLoaderListener 初始化的容器,或者 web.xml中定义的ContextLoaderServlet和配置 看起来像这样:

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

    在上面的配置中,我要求 spring 从 匹配 *-context.xml 并创建应用程序的类路径 来自它的上下文。例如,此上下文可能包含组件 例如中间层事务服务、数据访问对象或 您可能想要使用(和重用)的其他对象 应用。每个应用程序将有一个应用程序上下文。

    另一个上下文是“WebApplicationContext”,它是孩子 应用程序上下文的上下文。中定义的每个 DispatcherServlet Spring Web 应用程序将有一个关联的 Web 应用程序上下文。 WebApplicationContext的初始化 发生这样的事情:

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

    您将 spring 配置文件的名称作为 servlet 提供 初始化参数。这里要记住的重要一点是 XML 的名称必须采用 -servlet 形式。 xml。 在本例中,servlet 的名称是 platform-services 因此我们的 XML 的名称必须是 platform-service-servlet.xml。 可以引用 ApplicationContext 中可用的任何 bean 从每个 WebApplicationContext。最好的做法是保持 业务逻辑等中间层服务之间的清晰分离 组件和数据访问类(通常在 ApplicationContext) 和 Web 相关的组件,例如控制器 并查看解析器(在每个 WebApplicationContext 中定义) Dispatcher Servlet)。

    检查这些链接

    Difference between applicationContext.xml and spring-servlet.xml in Spring Framework

    http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-basics

    【讨论】:

    • 提醒一下,请正确引用和链接您复制措辞的任何来源。我在上面已经这样做了,但请确保您以后也这样做。
    • 您能否提供如您所说的It is a best practice to keep a clear separation between middle-tier services...的示例
    【解决方案3】:

    Spring MVC 至少有 2 个容器 -

    1. 应用上下文声明者

      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/spring/root-context.xml</param-value>
      </context-param>
      
    2. Servlet 上下文由 -

      声明
      <servlet>
          <servlet-name>appServlet</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>servlet-context.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
      </servlet>
      

    Web 应用程序可以定义任意数量的DispatcherServlet。每个 servlet 将在自己的命名空间中运行,使用映射、处理程序等加载自己的应用程序上下文。只有 ContextLoaderListener 加载的根应用程序上下文(如果有)将被共享。因此可以有任意数量的子容器。

    【讨论】:

      【解决方案4】:

      • ApplicationContext 组件(bean)的注册表。
      • ApplicationContext 定义了在所有 servlet 之间共享的 bean,即每个 Web 应用程序的根上下文配置。
      • spring*-servlet.xml 在这里定义了与 WebApplicationContexts 相关的 bean DispatcherServlet
      • Spring 容器可以有一个或多个WebApplicationContexts

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-01
        • 2021-06-28
        • 1970-01-01
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-07
        相关资源
        最近更新 更多