Remplacer une fève à l'intérieur du printemps conteneur au cours de l'exécution
Suppose que je définir un bean (par exemple BeanA) à l'intérieur du Printemps conteneur, et ce bean est injecté dans un objet. (par exemple BeanAUser)
Au cours de l'exécution, puis-je utiliser un autre exemple d'haricot pour remplacer l'original BeanA à l'intérieur du printemps contenant???? Et aussi ré-injecte cette nouvelle instance de bean dans BeanAUser afin de remplacer l'original BeanA?
- Je ne pense pas que cela est possible. Vous devriez probablement envisager d'autres solutions. Mais attendons de voir si soemone pouvez venir avec une solution.
- Quelle est votre cas ? Mieux vaut savoir ce qui est contraignante pour ce faire.
Vous devez vous connecter pour publier un commentaire.
Il peut être facilement réalisé à l'aide d'un proxy. Créer de la délégation de la mise en œuvre de votre interface et de l'objet de commutation, il est déléguant à la.
setTarget
. La question n'a pas d'inclure des détails permettant à toute solution plus personnalisée.Printemps a présenté le nouveau RefreshScope pour remplacer un haricot au moment de l'exécution. En interne, un proxy est créé, comme décrit dans le réponse de mrembisz.
La façon dont je voudrais le faire à l'aide d'un système appelé arbitraire de la méthode de remplacement.
Créer une classe qui implémente
org.springframework.beans.factory.support.MethodReplacer
, cela va vous forcer à créer une méthode commeLes paramètres ont la signification suivante:
Donc j'imagine que votre classe à ressembler à quelque chose comme ce qui suit
Dans votre configuration spring, vous demandez Printemps pour remplacer la
getBeanX()
méthode sur votreBeanAUser
commeJ'espère que j'ai compris votre problème correctement 🙂
replaced-method
balise lors de la création de haricots à l'aide de l'Annotation@Bean
En supposant
MyClass
dans mrembisz la réponse n'est pas définitive, on n'a pas à mettre en oeuvre le décorateur modèle manuellement et on peut l'appliquer automatiquement à l'aide deBeanPostProcessor
. Tout d'abord, définir l'extension de l'interface pour l'injection de nouvelles déléguer la mise en œuvre:Puis créer
BeanPostProcessor
qui enveloppe toutes les implémentations deMyInterface
à CGLIB proxy. Proxy sert à la fois deMyClass
(qui lui permet d'être injecté dans les champs deMyClass
type) etWrapper
(ce qui lui permet de changer de cible). Proxy redirige les originaux de toutes les invocations àMyClass
cible (qui est initialement réglé sur la valeur déclarée au Printemps), l'invocation deWrapper.setTarget
résultats dans l'objectif de changement.Simplement l'idée est la suivante: définir le haricot au Printemps comme il était normal de haricot, de le modifier après l'initialisation.
Il existe des moyens pour manipuler printemps contexte avant qui l'a créé.
Une certaine façon, vous utilisez GenericApplicationContext et GenericBeanDefinition classes pour manipuler contexte. Exemple de code suivant montre cette solution :
par cet extrait de code, vous pouvez ajouter, supprimer ou modifier les haricots avant de création.
Vous êtes de passage d'une fine ligne ici. Fondamentalement, vous tentez de mettre de la logique de l'application au Printemps conteneur. Éviter de programmation avec vos fichiers de configuration et l'utilisation de Printemps (ou ce que DI-cadre) uniquement pour le câblage de base.
Le proxy suggestion @mrembisz fait est donc préféré. De cette façon, la logique de l'application et de la configuration sont séparés.
Une autre approche peut être l'utilisation Atomique de Référence de votre classe comme un Haricot au lieu d'utiliser la classe directement. Ensuite, vous pouvez injecter Atomique de Référence de n'importe où et de les mettre à jour. Tous les autres services d'utiliser la dernière version de votre classe après la mise à jour il atomique de référence. Et je pense que cela a du sens.
Lire ce atomique de référence utilisation: https://stackoverflow.com/a/24765321/5197662
Un inconvénient de cette approche est de perdre que le printemps ne peut pas traiter les annotations de votre classe. Par exemple, u ne peut pas utiliser
@Cachable
,@Async
,@PreDestroy
et les autres. Mais la solution est bonne, quand u juste besoin d'un objet et ses propriétés.