java - Primavera: ¿Por qué el contexto de la aplicación "raíz" y el contexto de la aplicación "servlet" son creados por diferentes partes?
spring tomcat (1)
Según tengo entendido, una aplicación web basada en Spring se inicializa de la siguiente manera:
Paso 1 : el Servlet container (eg Tomcat)
localiza la implementación de ServletContainerInitializer
, que es SpringServletContainerInitializer
.
Paso 2 : SpringServletContainerInitializer
crea DispatcherServlet
y ContextLoaderListener
Paso 3 : DispatcherServlet
crea el servlet application context
. Y ContextLoaderListener
crea un root application context
.
El paso 1 está definido por la especificación de Servlet 3.0. Los pasos 2 y 3 están totalmente definidos por Spring.
Puedo ver la racionalidad de poner web
beans en contexto de servlet y beans non-web
en contexto raíz . Pero ¿por qué tenemos que crear estos 2 contextos en diferentes lugares, es decir, DispatcherServlet
y ContextLoaderListener
?
Si todo lo que queremos es solo preparar todo lo necesario, ¿por qué no simplemente crear ambos contextos en ContextLoaderListener
ya que puede verse como el método main()
de toda la aplicación web? Creo que eso es más lógico y el enfoque actual solo complica las cosas.
ADD 1
Basado en la respuesta de @Shailendra, dibujo esto:
Según tengo entendido, Spring presentó los conceptos de application context
la application context
y los almacenó en el Servlet Context
. Servlet Context es un concepto introducido por java servlet technolgoy.
Supongo que la implementación de DispatcherServlet
debe tener una variable miembro para mantener la key
de su servlet application context
en el servlet context
. Por lo tanto, puede acceder a su propio contexto. Tal vez la clave sea el nombre del servlet.
Y el root application context
debe tener una clave conocida para que todos puedan acceder a ella.
ADD 2
La clave más conocida para el root application context
es esta:
(en org.springframework.web.context.WebApplicationContext
)
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
ADD 3
El DispatcherServlet
tiene una referencia a su WebApplicationContext
. Hereda el siguiente memeber de FrameworkServlet
:
/** WebApplicationContext for this servlet */
private WebApplicationContext webApplicationContext;
Y
public FrameworkServlet(WebApplicationContext webApplicationContext) {
this.webApplicationContext = webApplicationContext;
}
Pero ¿por qué tenemos que crear estos 2 contextos en diferentes lugares, es decir, DispatcherServlet y ContextLoaderListener
Porque se supone que los dos contextos son diferentes pero tienen una relación jerárquica para poder anular. Normalmente, el contexto cargado mediante ContextLoaderListener
es el contexto "raíz" que pertenece a la aplicación completa, mientras que el que se inicializó utilizando DispatcherServlet
es realmente específico para ese servlet. Técnicamente, puede tener múltiples servlets en una aplicación y múltiples contextos de este tipo, cada uno específico para el respectivo servlet pero con el mismo contexto raíz. Para más detalles, vea otra de mis respuestas aquí .