Existe-t-il un moyen de demander statiquement / globalement une copie d'ApplicationContext dans une application Spring?
En supposant que la classe principale démarre et initialise le contexte de l'application, doit-elle le transmettre à travers la pile d'appels à toutes les classes qui en ont besoin, ou existe-t-il un moyen pour une classe de demander le contexte créé précédemment? (Ce qui, je suppose, doit être un singleton?)
la source
instance()
méthode du singleton comme usine. Cependant, je pense que je laisse tout le code en dehors du conteneur accéder au conteneur en premier. Ensuite, ce code pourrait demander des objets au conteneur.Vous pouvez implémenter
ApplicationContextAware
ou simplement utiliser@Autowired
:SpringBean
auraApplicationContext
injecté, dans lequel ce bean est instancié. Par exemple, si vous avez une application Web avec une hiérarchie de contextes assez standard:et
SpringBean
est déclaré dans le contexte principal, il aura injecté le contexte principal; sinon, s'il est déclaré dans le contexte MVC, le contexte MVC sera injecté.la source
@Inject
également utiliserVoici une belle façon (pas la mienne, la référence d'origine est ici: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
J'ai utilisé cette approche et cela fonctionne bien. Fondamentalement, c'est un bean simple qui contient une référence (statique) au contexte de l'application. En le référençant dans la configuration du printemps, il est initialisé.
Jetez un oeil à la référence d'origine, c'est très clair.
la source
getBean
partir d'un code qui s'exécute pendant un test unitaire car le contexte Spring ne sera pas configuré avant que vous ne le demandiez. C'est une condition de course dans laquelle je viens de claquer aujourd'hui après 2 ans d'utilisation réussie de cette approche.Je pense que vous pouvez utiliser SingletonBeanFactoryLocator . Le fichier beanRefFactory.xml contiendrait le contexte d'application réel, il ressemblerait à ceci:
Et le code pour obtenir un bean à partir du contexte d'application où que ce soit quelque chose comme ça:
L'équipe de Spring décourage l'utilisation de cette classe et du yadayada, mais cela me convient bien là où je l'ai utilisé.
la source
Avant de mettre en œuvre l'une des autres suggestions, posez-vous ces questions ...
Les réponses à ces questions sont plus faciles dans certains types d'applications (applications Web, par exemple) que dans d'autres, mais valent quand même la peine d'être posées.
L'accès à ApplicationContext viole en quelque sorte le principe d'injection de dépendance dans son ensemble, mais parfois vous n'avez pas beaucoup de choix.
la source
Si vous utilisez une application Web, il existe également un autre moyen d'accéder au contexte de l'application sans utiliser de singletons en utilisant un servletfilter et un ThreadLocal. Dans le filtre, vous pouvez accéder au contexte d'application à l'aide de WebApplicationContextUtils et stocker le contexte d'application ou les beans nécessaires dans TheadLocal.
Attention: si vous oubliez de désinstaller le ThreadLocal, vous aurez des problèmes désagréables en essayant de retirer l'application! Ainsi, vous devez le définir et commencer immédiatement un essai qui désactive le ThreadLocal dans la partie finale.
Bien sûr, cela utilise toujours un singleton: le ThreadLocal. Mais les haricots réels n'ont plus besoin d'être. La portée peut même être limitée à la demande, et cette solution fonctionne également si vous avez plusieurs fichiers WAR dans une application avec les bibliothèques dans le fichier EAR. Pourtant, vous pourriez considérer cette utilisation de ThreadLocal aussi mauvaise que l'utilisation de singletons simples. ;-)
Peut-être que Spring propose déjà une solution similaire? Je n'en ai pas trouvé, mais je n'en suis pas sûr.
la source
Source: http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html
la source
Jetez un œil à ContextSingletonBeanFactoryLocator . Il fournit des accesseurs statiques pour saisir les contextes de Spring, en supposant qu'ils ont été enregistrés de certaines manières.
Ce n'est pas joli et plus complexe que vous ne le souhaiteriez peut-être, mais cela fonctionne.
la source
Il existe de nombreuses façons d'obtenir le contexte d'application dans l'application Spring. Ceux-ci sont donnés ci-dessous:
Via ApplicationContextAware :
Ici
setApplicationContext(ApplicationContext applicationContext)
, vous obtiendrez l'applicationContextVia Autowired :
Ici, le
@Autowired
mot-clé fournira l'applicationContext. Autowired a un problème. Cela créera un problème lors des tests unitaires.la source
Notez qu'en stockant n'importe quel état du courant
ApplicationContext
ou leApplicationContext
lui - même dans une variable statique - par exemple en utilisant le modèle singleton - vous rendrez vos tests instables et imprévisibles si vous utilisez Spring-test. En effet, Spring-test met en cache et réutilise les contextes d'application dans la même JVM. Par exemple:@ContextConfiguration({"classpath:foo.xml"})
.@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})
@ContextConfiguration({"classpath:foo.xml"})
Lorsque le test A s'exécute, un
ApplicationContext
est créé et tout beanApplicationContextAware
implémentant ou câblage automatiqueApplicationContext
peut écrire dans la variable statique.Lorsque le test B s'exécute, la même chose se produit et la variable statique pointe désormais vers les tests B
ApplicationContext
Lorsque le test C s'exécute, aucun bean n'est créé car le
TestContext
(et ici leApplicationContext
) du test A est réutilisé. Vous avez maintenant une variable statique pointant vers une autreApplicationContext
que celle contenant actuellement les beans pour votre test.la source
Je ne sais pas à quel point cela sera utile, mais vous pouvez également obtenir le contexte lorsque vous initialisez l'application. C'est le plus tôt possible pour obtenir le contexte, même avant un
@Autowire
.la source
Veuillez noter que; le code ci-dessous créera un nouveau contexte d'application au lieu d'utiliser celui déjà chargé.
Notez également que cela
beans.xml
devrait faire partie dessrc/main/resources
moyens de guerre dont il fait partieWEB_INF/classes
, où la vraie application sera chargée viaapplicationContext.xml
mentionné àWeb.xml
.Il est difficile de mentionner le
applicationContext.xml
chemin dans leClassPathXmlApplicationContext
constructeur.ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")
ne pourra pas localiser le fichier.Il est donc préférable d'utiliser le contexte d'application existant en utilisant des annotations.
la source
Je sais que cette question reçoit une réponse, mais je voudrais partager le code Kotlin que j'ai fait pour récupérer le contexte de printemps.
Je ne suis pas un spécialiste, donc je suis ouvert aux critiques, critiques et conseils:
https://gist.github.com/edpichler/9e22309a86b97dbd4cb1ffe011aa69dd
Désormais, un contexte Spring est accessible au public, pouvant appeler la même méthode indépendamment du contexte (tests junit, beans, classes instanciées manuellement) comme sur ce servlet Java:
la source
Effectuez le câblage automatique dans Spring Bean comme ci-dessous: @Autowired private ApplicationContext appContext;
vous serez l'objet applicationcontext.
la source
Approche 1: vous pouvez injecter ApplicationContext en implémentant l'interface ApplicationContextAware. Lien de référence .
Approche 2: Contexte d'application Autowire dans l'un des beans gérés par le printemps.
Lien de référence .
la source