Spring créant plusieurs instances d'un singleton?
J'ai un graphique de beans Spring qui autowire les uns des autres. Fortement illustration simplifiée:
<context:annotation-config/>
<bean class="Foo"/>
<bean class="Bar"/>
<bean class="Baz"/>
...
public class Foo {
@Autowired Bar bar;
@Autowired Baz baz;
}
public class Bar {
@Autowired Foo foo;
}
public class Baz {
@Autowired Foo foo;
}
Tous ces haricots n'ont pas de portée spécifiée, ce qui implique, ils sont des singletons (en les rendant explicites les singletons ne change rien, j'ai essayé).
Le problème est que, après l'instanciation d'un seule de contexte de l'applicationles instances de Bar
et Baz
contenir différents instances de Foo
. Comment est-ce possible?
J'ai essayé de créer publique n'args constructeur de Foo
et de débogage a confirmé Foo
est créé plus d'une fois. La trace de la pile pour l'ensemble de ces créations est ici.
J'ai aussi essayé d'activer la journalisation du débogage pour le Printemps, et parmi toutes les autres lignes, le suivant:
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
Je comprends que mes haricots sont croisant les uns des autres, mais je m'attends à ce Printemps-cadre à l'égard portée singleton et initialiser un singleton bean une fois, et puis autowire à qui il veut.
Le fait intéressant que, si j'utilise de la vieille école private
constructeur avec public static Foo getInstance
accesseur, cela fonctionne bien - aucune exception n'est levée pendant le contexte de l'installation.
FWIW, je suis à l'aide de Printemps version 3.0.5 (aussi essayé avec 3.1.2, même résultats), avec o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)
constructeur.
Je peut facilement convertir mon code pour l'utilisation de l'initialiseur statique, mais je veux comprendre pourquoi le Printemps se comporter de cette façon. Est-ce un bug?
EDIT: supplémentaire de l'enquête a montré que
- Après le contexte de l'application est initialisé, toutes les demandes ultérieures de
context.getBean(Foo.class)
toujours retour la même instance deFoo
. - Remplacement
@Autowired
avec les setters (environ 20 usages de ce bean) encore de résultats multiples constructions de cet objet, mais toutes les dépendances sont injectés avec la même de référence.
Pour moi au-dessus suggère que c'est un Printemps bug concernant @Autowired
mise en œuvre. Je vais poster au Printemps, des forums communautaires et après revenir ici si j'arrive à obtenir quelque chose d'utile.
source d'informationauteur mindas
Vous devez vous connecter pour publier un commentaire.
Enfant contexte(s) peut retrouver le même singleton haricots si vous n'êtes pas prudent avec context:component-scan annotations (il y a d'autres Printemps contexte d'analyse des annotations en tant que bien tels que MVC et autres). C'est un problème courant lors de l'utilisation de Ressort de servlets dans les applications web, voir Pourquoi DispatcherServlet crée un autre contexte de l'application?
Assurez-vous que vous n'êtes pas re-numérisation de vos composants de l'enfant contextes, ou de la numérisation uniquement des forfaits spécifiques/annotations et à l'exclusion des forfaits dit/annotations à partir de la racine de contexte composant d'analyse.
Pour une raison quelconque, nous obtenons cette apparition au hasard dans les tests d'intégration et de services (printemps version 4.1.4, java 1.8).
Ressemble il pourrait y avoir plus d'un coupable permettra à l'autowiring semble être à l'origine de ce au premier.
Cependant, nous avons résolu le plus cohérent des échecs, en nous assurant de donner à chaque touchés bean un champ 'id'.
Essayez d'utiliser l'injection par mutateur au lieu de constructeur et de voir si cela fonctionne.Au printemps de haricots xml spécifier Un Haricot ref Bean B et vice versa.
Mon Ressort de la configuration comme suit:
Classes sont identiques à la vôtre
Application de Test comme suit:
Sortie à partir de l'application de test comme suit:
À l'aide de 3.0.6 il fonctionne parfaitement bien (singleton, les haricots sont en effet des singletons). Il pourrait être quelque chose d'autre que vous n'avez pas d'illustrer ici gâcher votre configuration. Bien sûr, comme une note de côté, à l'aide de package par défaut peut causer certains mystérieux de la magie pour arriver 😉