About multiple containers in spring framework

2019-01-12 17:30发布

问题:

In a typical Spring MVC project there two "containers": One created by ContextLoaderListener and the other created by DispatchServlet.

I want to know, are these really two IoC container instance?( I see two bean config files, one is root-context.xml the other is servlet-context.xml)

If there are 2 containers, then what's the relationship?

Can the beans declared in one container be used in the other?

回答1:

From the Spring Official Website:

The interface org.springframework.context.ApplicationContext represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the aforementioned beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code.

Again from official Doc:

In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.

Now coming to your Question, as is stated here:

In Spring Web Applications, there are two types of container, each of which is configured and initialized differently. One is the “Application Context” and the other is the “Web Application Context”. Lets first talk about the “Application Context”. Application Context is the container initialized by a ContextLoaderListener or ContextLoaderServlet defined in the web.xml and the configuration would look something like this:

<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>

In the above configuration, I am asking spring to load all files from the classpath that match *-context.xml and create an Application Context from it. This context might, for instance, contain components such as middle-tier transactional services, data access objects, or other objects that you might want to use (and re-use) across the application. There will be one application context per application.

The other context is the “WebApplicationContext” which is the child context of the application context. Each DispatcherServlet defined in a Spring web application will have an associated WebApplicationContext. The initialization of the WebApplicationContext happens like this:

<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>

You provide the name of the spring configuration file as a servlet initialization parameter. What is important to remember here is that the name of the XML must be of the form -servlet. xml. In this example, the name of the servlet is platform-services therefore the name of our XML must be platform-service-servlet.xml. Whatever beans are available in the ApplicationContext can be referred to from each WebApplicationContext. It is a best practice to keep a clear separation between middle-tier services such as business logic components and data access classes (that are typically defined in the ApplicationContext) and web- related components such as controllers and view resolvers (that are defined in the WebApplicationContext per Dispatcher Servlet).

Check these links

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



回答2:

There aren't two separate containers created. Typically, you want spring to instantiate the object declared in the servlet-context.xml when the object is required. So, you map the servlet-context.xml configuration file to the Dispatcher Servlet i.e. you want to initialize the object when a request hits the 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>

Where as, if you want to initialize the object and perform action when the context is being loaded you would declare the configuration file with in the context-param tags of your deployment descriptor.

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

You could test this out by writing by declaring separate beans in the servlet-context.xml and root-context.xml and then, autowiring them in a custom Context Loader Listener class. You would find only the root-context instances are initialized and servlet-context beans are null.



回答3:

Spring MVC have atleast 2 container -

  1. Application Context declared by

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>
    
  2. Servlet context declared by -

    <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>
    

And a web application can define any number of DispatcherServlet's. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. Only the root application context as loaded by ContextLoaderListener, if any, will be shared. Thus can have any number of child containers.



回答4:

  • ApplicationContext a registry of components (beans).
  • ApplicationContext defines the beans that are shared among all the servlets i.e. root context configuration for every web application.
  • spring*-servlet.xml defines the beans that are related WebApplicationContexts here DispatcherServlet.
  • Spring container can have either single or multiple WebApplicationContexts.