Dans un projet Spring MVC typique, il y a deux "conteneurs": l'un créé par ContextLoaderListener et l'autre créé par DispatchServlet.
Je veux savoir s'il s'agit vraiment de deux instances de conteneur IoC? (Je vois deux fichiers de configuration de bean, l'un est root-context.xml
l'autre est servlet-context.xml
)
S'il y a 2 conteneurs, alors quelle est la relation?
Les grains déclarés dans un récipient peuvent-ils être utilisés dans l'autre?
Depuis le Site officiel du printemps :
L'interface
org.springframework.context.ApplicationContext
représente le conteneur Spring IoC et est responsable de l'instanciation, de la configuration et de l'assemblage des beans susmentionnés. Le conteneur obtient ses instructions sur les objets à instancier, à configurer et à assembler en lisant les métadonnées de configuration. Les métadonnées de configuration sont représentées en XML, Java annotations, ou Java code.
Encore une fois du Doc officiel:
Dans la structure Web MVC, chaque DispatcherServlet a son propre WebApplicationContext, qui hérite de tous les beans déjà définis dans la racine WebApplicationContext. Ces beans hérités peuvent être remplacés dans la portée spécifique au servlet, et vous pouvez définir de nouveaux beans spécifiques à la portée locaux à une instance de servlet donnée.
Venons-en maintenant à votre question, comme indiqué ici :
Dans Spring Web Applications, il existe deux types de conteneurs, chacun étant configuré et initialisé différemment. L'un est le "contexte d'application" et l'autre est le "contexte d'application Web". Parlons d'abord du "contexte d'application". Le contexte d'application est le conteneur initialisé par un ContextLoaderListener ou ContextLoaderServlet défini dans le web.xml et la configuration ressemblerait à ceci:
<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>
Dans la configuration ci-dessus, je demande à spring de charger tous les fichiers du chemin de classe qui correspondent à * -context.xml et de créer un contexte d'application à partir de celui-ci. Ce contexte peut, par exemple, contenir des composants tels que des services transactionnels de niveau intermédiaire, des objets d'accès aux données ou d'autres objets que vous pourriez souhaiter utiliser (et réutiliser) dans l'application. Il y aura un contexte d'application par application.
L'autre contexte est le "WebApplicationContext" qui est le contexte enfant du contexte d'application. Chaque DispatcherServlet défini dans une application Web Spring aura un WebApplicationContext associé. L'initialisation de WebApplicationContext se produit comme ceci:
<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>
Vous fournissez le nom du fichier de configuration Spring en tant que paramètre d'initialisation de servlet. Ce qui est important à retenir ici, c'est que le nom du XML doit être du formulaire -servlet. xml. Dans cet exemple, le nom du servlet est platform-services donc le nom de notre XML doit être platform-service-servlet.xml. Les beans disponibles dans ApplicationContext peuvent être référencés à partir de chaque WebApplicationContext. Il est recommandé de maintenir une séparation claire entre les services de niveau intermédiaire tels que les composants de logique métier et les classes d'accès aux données (qui sont généralement définis dans ApplicationContext) et les composants liés au Web tels que les contrôleurs et les résolveurs de vue (qui sont définis dans le WebApplicationContext par Dispatcher Servlet).
Vérifiez ces liens
Différence entre applicationContext.xml et spring-servlet.xml dans Spring Framework
Il n'y a pas deux conteneurs distincts créés. En règle générale, vous souhaitez que spring instancie l'objet déclaré dans le servlet-context.xml lorsque l'objet est requis. Ainsi, vous mappez le fichier de configuration servlet-context.xml sur le servlet Dispatcher, c'est-à-dire que vous souhaitez initialiser l'objet lorsqu'une demande atteint le servlet dispatcher.
<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>
Dans le cas où, si vous souhaitez initialiser l'objet et effectuer une action lors du chargement du contexte, vous déclareriez le fichier de configuration avec dans le context-param
balises de votre descripteur de déploiement.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
Vous pouvez tester cela en écrivant en déclarant des beans séparés dans servlet-context.xml et root-context.xml puis en les câblant automatiquement dans une classe d'écouteur de chargeur de contexte personnalisé. Vous constateriez que seules les instances de contexte racine sont initialisées et que les beans de contexte de servlet sont nuls.
ApplicationContext
un registre de composants (beans).ApplicationContext
définit les beans partagés entre tous les servlets, c'est-à-dire la configuration du contexte racine pour chaque application Web.spring*-servlet.xml
définit les beans associés WebApplicationContexts
ici DispatcherServlet
.WebApplicationContexts
.Spring MVC ont au moins 2 conteneurs -
Contexte d'application déclaré par
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
Contexte de servlet déclaré par -
<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>
Et une application Web peut définir n'importe quel nombre de DispatcherServlet
. Chaque servlet fonctionnera dans son propre espace de noms, chargeant son propre contexte d'application avec des mappages, des gestionnaires, etc. Seul le contexte d'application racine tel que chargé par ContextLoaderListener
, le cas échéant, sera partagé. Ainsi peut avoir n'importe quel nombre de conteneurs enfants.