在典型的 Spring MVC 项目中,有两个“容器”:一个由 ContextLoaderListener 创建,另一个由 DispatchServlet 创建。
我想知道,这真的是两个 IoC 容器实例吗?(我看到两个 bean 配置文件,一个是root-context.xml
另一个servlet-context.xml
)
如果有2个容器,那是什么关系?
在一个容器中声明的 bean 可以在另一个容器中使用吗?
在典型的 Spring MVC 项目中,有两个“容器”:一个由 ContextLoaderListener 创建,另一个由 DispatchServlet 创建。
我想知道,这真的是两个 IoC 容器实例吗?(我看到两个 bean 配置文件,一个是root-context.xml
另一个servlet-context.xml
)
如果有2个容器,那是什么关系?
在一个容器中声明的 bean 可以在另一个容器中使用吗?
来自春季官网:
该接口
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的区别
没有创建两个单独的容器。通常,您希望 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 为空。
Spring MVC 至少有 2 个容器 -
应用程序上下文声明者
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
由 - 声明的 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
如果有)将被共享。因此可以有任意数量的子容器。