41

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

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

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

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

4

4 回答 4

49

来自春季官网

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

再次来自官方文档:

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

现在来回答您的问题,如此处所述

在 Spring Web Applications 中,有两种类型的容器,每种容器的配置和初始化都不同。一个是“应用程序上下文”,另一个是“Web 应用程序上下文”。让我们先谈谈“应用程序上下文”。Application Context 是由 web.xml 中定义的 ContextLoaderListener 或 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”,它是应用程序上下文的子上下文。在 Spring Web 应用程序中定义的每个 DispatcherServlet 都会有一个关联的 WebApplicationContext。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 相关组件(例如控制器和视图解析器)(在每个 Dispatcher Servlet 的 WebApplicationContext)。

检查这些链接

Spring Framework中applicationContext.xml和spring-servlet.xml的区别

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

于 2013-09-02T20:24:07.600 回答
5

没有创建两个单独的容器。通常,您希望 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 为空。

于 2013-09-02T17:56:46.947 回答
2

在此处输入图像描述

  • ApplicationContext组件(bean)的注册表。
  • ApplicationContext定义在所有 servlet 之间共享的 bean,即每个 Web 应用程序的根上下文配置。
  • spring*-servlet.xml定义与WebApplicationContexts此处相关的 bean DispatcherServlet
  • Spring 容器可以有单个或多个WebApplicationContexts.
于 2018-05-26T02:30:36.437 回答
1

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如果有)将被共享。因此可以有任意数量的子容器。

于 2017-02-16T07:01:20.820 回答