Aide / explication de la hiérarchie de configuration du fichier XML de spring

Lorsque j’ai commencé à apprendre sur Spring, les choses étaient configurées dans le fichier applicationContext.xml. Alors que je commençais à lire des livres spécifiquement sur des versions plus récentes de Spring, ils ont tous fait la configuration dans des fichiers XML distincts tels que myapp-servlet-xml, myapp-security.xml, myapp-service.xml, etc. configurer un contextConfigLocation dans le fichier web.xml. Ainsi, par exemple, le code que j’ai suivi avec ceci était comme contextConfigLocation:

 contextConfigLocation  /WEB-INF/myapp-servlet.xml /WEB-INF/myapp-data.xml   

Quoi qu’il en soit, récemment, je suis tombé sur un problème de configuration (que les personnes utiles de StackOverflow m’ont aidé à comprendre) à cause de cette séparation. Il n’y avait pas de fichier applicationContext.xml pour les exemples de ces livres et plus tard, lorsque j’ai essayé d’append l’parsing automatique et les annotations à l’application, cela entraînait des problèmes. J’ai essayé de tout déplacer dans applicationContext.xml et de supprimer les autres fichiers pour résoudre le problème. Rien d’autre n’a changé, je viens de mettre tout dans applicationContext.xml.

Ainsi, avec les commentaires des autres, cela m’a permis de comprendre que même si vous ne créez pas une applicationContext.xml, elle est toujours utilisée et constitue le premier niveau d’une hiérarchie de configuration. J’espère que quelqu’un d’autre pourra m’expliquer comment tout cela fonctionne, car je n’ai trouvé aucune explication à ce sujet.

Par exemple, si je mets certaines balises context: dans des fichiers de configuration situés sous applicationContext.xml, certaines classes risquent de ne pas être analysées. Des choses de cette nature. Je ne comprends pas la préséance et ce qui doit être fait pour s’assurer qu’il est vu à l’échelle de l’application, et ainsi de suite. Si quelqu’un peut l’expliquer clairement ou me diriger vers une ressource qui l’explique, j’apprécierais beaucoup, merci. J’espère que ce que je demande a du sens.

Le fichier “applicationContext.xml” n’a rien de particulier, sauf que c’est le nom que Spring attend de lui en tant que fichier de configuration par défaut. L’utilisation d’un fichier nommé cela ou de plusieurs fichiers nommés “dog.xml”, “cat.xml” et “alien.xml” fonctionneront exactement de la même manière. Le problème que vous rencontrez est d’avoir plusieurs ApplicationContexts utilisés en même temps, et non pas d’avoir plusieurs fichiers XML. J’ai récemment répondu à quelques questions de personnes qui avaient des problèmes causés par la non-compréhension de ces concepts. Consultez ces réponses et voyez quelles questions vous avez encore:

Déclaration du bean Spring dans un contexte parent par rapport au contexte enfant

Spring-MVC: Qu’est-ce qu’un “contexte” et un “espace de noms”?

Edit: En réponse à votre nouvelle question:

J’avais une dans mon servlet.xml.

Je suppose que ce fichier “servlet.xml” est nommé foo-servlet.xml , où le DispatcherServlet configuré dans votre fichier web.xml est nommé “foo”, comme

  foo org.springframework.web.servlet.DispatcherServlet  

Par convention, lorsque ce DispatcherServlet démarre, il crée un nouveau ApplicationContext configuré par le fichier foo-servlet.xml , dérivé du servlet-name . Maintenant, comme vous mettez un context:component-scan , il va parsingr récursivement le paquet donné et créer des beans pour toutes les classes annotées. Le package que vous lui avez fourni, com.myapp , ressemble au package de base de toute votre application. Spring créera donc des beans à partir de toutes les classes annotées de votre application, y compris celles d’access aux données, dans ce seul ApplicationContext associé à l’application. DispatcherServlet. En règle générale, ce contexte ne doit comporter que des éléments de couche de visualisation et des beans qui prennent directement en charge le DispatcherServlet, ce qui constitue une erreur de configuration.

Dans mon fichier data.xml, j’avais des beans de source de données et c’était tout. Aucun autre haricot, tout le rest a été automatisé et annoté.

Ce fichier “data.xml” est probablement celui que vous avez répertorié dans le contexte contextConfigLocation . En supposant que vous avez également ajouté ContextLoaderListener à votre fichier web.xml , comme

  org.springframework.web.context.ContextLoaderListener  

alors ce fichier sera utilisé pour créer un second ApplicationContext – le contexte racine. C’est ce que fait l’auditeur. Notez que cela crée réellement le contexte à partir de tous les fichiers listés dans contextConfigLocation , et si vous avez également inclus votre “servlet.xml” dans cette liste, alors vous avez chargé cette configuration deux fois: ici dans le contexte racine et dans le contexte associé au DipatcherServlet. J’espère que vous voyez maintenant comment il y a une division distincte entre les fichiers de configuration XML et ApplicationContexts qu’ils configurent. Le même fichier XML peut facilement être utilisé pour configurer deux contextes différents. Que cela soit correct ou non est une autre question. Dans ce cas particulier, ce n’est pas le cas.

L’ordre dans lequel j’ai décrit ces deux contextes est en réalité rétrograde. Je suivais juste votre description de ce que vous avez fait. ContextLoaderListener, étant un ServletContextListener , s’exécutera toujours avant le démarrage de toute servlet. Cela signifie que le contexte racine est créé en premier et l’autre contexte en second. C’est par conception que lorsque le DispatcherServlet crée son contexte, il peut append ce contexte en tant qu’enfant du contexte racine. J’ai décrit cette relation dans ces autres articles. L’effet le plus important de ceci est que les beans dans le contexte racine sont disponibles pour et via le contexte du DispatcherServlet. Cela vaut également pour les relations automatisées. C’est important car le DispatcherServlet recherche uniquement dans le contexte associé les beans dont il a besoin, comme les instances de contrôleur. Vos contrôleurs doivent cependant être câblés avec des haricots. Ainsi, les contrôleurs vivent traditionnellement dans le contexte de DispatcherServlet et les beans de support vivent dans le contexte racine.

J’ai ensuite essayé d’append @Transacational à mon bean de service et cela ne persisterait pas.

Pour que @Transactional fonctionne, vous devez inclure la dans la configuration de ApplicationContext où réside le bean annoté. L’astuce consiste à trouver la partie “où elle vit”. Les beans dans un enfant peuvent remplacer les beans dans un contexte parent. Par conséquent – je devine juste ici – si vous avez chargé tous vos beans dans le contexte DispatcherServlet comme je l’ai décrit ci-dessus, mais que vous placez le dans le contexte racine, vous pourriez avoir un bean dans le contexte racine c’est correctement transactionnel, mais ce n’est pas celui qui est utilisé car le doublon est “plus proche” du servlet dans la hiérarchie parent / enfant et le contexte dans lequel il se trouve n’a pas reçu de configuration .

Lorsque j’ai modifié le contexte de servlet: balise component-scan pour indiquer à la place com.myapp.web, puis ajouté une balise context: component-scan au fichier data.xml, tout a fonctionné.

Cela dépend toujours quelque peu des fichiers de configuration que vous incluiez dans ApplicationContexts, mais au moins, je peux dire qu’en faisant cela, vous avez supprimé beaucoup de beans du contexte de DispatcherServlet, qui posaient des problèmes. En particulier, vos beans @Transactional correctement configurés dans le contexte racine ne seraient plus ombrés par les beans dans le contexte enfant et seraient injectés dans vos contrôleurs, de sorte que vos éléments de persistance fonctionneraient alors.

Donc, la principale chose à retenir est que vous avez deux ApplicationContexts liés. Vous devez restr conscient de ce fait et garder le contrôle des fèves dans quel contexte.

Est-ce que ça couvre tout?