Supposons que j'ai un projet Spring Java et que j'essaie de le configurer en tant que servlet de serveur Web. Voici une version allégée du fichier web.xml :
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/generalApplicationContext.xml
</param-value>
</context-param>
<servlet>
<servlet-name>my-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/specificApplicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my-servlet</servlet-name>
<url-pattern>/foo/*</url-pattern>
</servlet-mapping>
L'essentiel à noter ici est que j'ai spécifié deux fichiers XML à charger. L'un est général pour l'ensemble de mon application, tandis que l'autre est spécifique au servlet "my-servlet". Pour une configuration avec un seul mappage de servlet, cela n'aurait aucun sens. Cependant, mon projet a plusieurs mappages de servlet et chacun a des paramètres Spring spécifiques.
Ma question: Quel contextConfigLocation va être chargé en premier d'ici Spring? Sera-ce le generalApplicationContext.xml ou sera-ce le specificApplicationContext.xml? Plus important encore, l'ordre de chargement est-il important? D'après mes efforts de débogage, il semble évident que c'est le cas car j'obtiens des erreurs différentes lorsque je déplace une configuration Spring indépendante d'un fichier à l'autre.
NB: La bonne pratique d'utiliser plusieurs configurations de ressorts pour plusieurs mappages de servlets est discutable. Il en va de même pour l'utilisation de la configuration XML au lieu de la nouvelle configuration Java. Mais ce n'est pas ce que j'essaie de demander ici. Essayons de nous concentrer sur ma question principale.
generalApplicationContext.xml
est celui qui sera chargé en premier car c'est le ApplicationContext
chargé avec le ContextLoaderListener
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/generalApplicationContext.xml
</param-value>
</context-param>
specificApplicationContext.xml
est en fait un contexte enfant de la charge ci-dessus generalApplicationContext.xml
et ce sera un WebApplicationContext
<servlet>
<servlet-name>my-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/specificApplicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my-servlet</servlet-name>
<url-pattern>/foo/*</url-pattern>
</servlet-mapping>
Et oui, l'ordre de chargement est important. Parce que lorsque le contexte parent est chargé, toutes les dépendances requises doivent être remplies.
La partie ci-dessous charge le fichier de contexte et crée le ApplicationContext . 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.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/generalApplicationContext.xml
</param-value>
</context-param>
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>my-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/specificApplicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Quelle meilleure façon d'avoir les journaux de débogage de Spring pour vous indiquer l'ordre. Si vous voulez entrer dans le code, vous pouvez également jeter un œil au org.springframework.web.servlet.FrameworkServlet
(DispatcherServlet
étend cette classe) Activez simplement l'enregistreur "org.springframework.web.servlet"
pour déboguer le niveau dans votre infrastructure de journalisation préférée
Voici à quoi ressemblent généralement les journaux - il est clair que le contexte racine est chargé en premier et est défini comme parent pour la hiérarchie de contexte - le contexte de servlet est chargé ensuite.
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/generalApplicatonContext.xml]
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 256 ms
DEBUG: org.springframework.web.servlet.DispatcherServlet - Initializing servlet 'my-servlet'
INFO :Initializing Spring FrameworkServlet 'appServlet'
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'my-servlet': initialization started
DEBUG: org.springframework.web.servlet.DispatcherServlet - Servlet with name 'appServlet' will try to create custom WebApplicationContext context of class 'org.springframework.web.context.support.XmlWebApplicationContext', using parent context [Root WebApplicationContext: startup date [Fri May 15 17:08:24 IST 2015]; root of context hierarchy
DEBUG: Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/specificApplicationContext.xml
Si vous rencontrez ContextLoaderListener dans votre ressort web.xml chargera le generalApplicationContext.xml en premier. Cela créera des beans et leur fournira tous les servlets et filtres. Ce xml doit avoir les classes communes, les beans qui sont utilisés dans votre application.
Plus tard, le conteneur de printemps chargera le specificApplicationContext.xml, car vous avez chargé au démarrage dans la configuration du servlet. Si vous ne spécifiez pas la charge au démarrage, ce specificApplicationContext.xml se chargera lorsque la première demande parviendra à votre application avec le modèle d'URL spécifique.
Comme votre question lorsque vous déplacez votre configuration de printemps d'une configuration à une autre, cela changera la disponibilité des ressources d'application dans le conteneur. Si vous spécifiez les beans Controller dans generalApplicationContext.xml et que vous ne les spécifiez pas dans specificApplicationContext.xml, votre DispatcherServlet ne trouvera pas les mappages, vous verrez donc une erreur 404.
Si vous souhaitez créer des objets bean à la demande, vous pouvez créer une configuration de servlet supplémentaire pour charger ce fichier spécifique spécifiqueConfigurationFile2.xml et le mapper au modèle d'URL.