La meilleure façon d'injecter une classe dont instanciation ne peut pas être contrôlée?
-
26-10-2019 - |
Question
Je suis assez nouveau pour Guice si nous espérons que ce n'est pas une question évidente ...
Je fais face à un cadre qui instancie dynamiquement un de mes cours d'application (Appelons-le C
) utilisant la réflexion, donc je ne contrôle pas son instanciation. De plus, il n'y a aucun moyen facile pour moi d'accéder à un C
nouvellement créé après que le cadre a instantitated il. Voici ce que C
ressemblerait à ceci:
public class C implements I { public C() { // this ctor is invoked by the framework so can't use DI here? } public void initialize() { // this is a post instantiation hook which the f/w will invoke } private void m() { Dependency d = Dependency.getInstance(); d.doSmth(); } }
Je voudrais C
à acquérir Dependency
en utilisant DI. Ici Dependency
est clairement un singleton, mais cela ne doit pas être le cas en général.
Je suis venu avec deux solutions possibles, dont aucun ne se sent très bien rangé, donc je pensais que je demande aux experts:
-
injection statique. Je lutte pour voir comment cela améliore considérablement sur le service de localisation anti-modèle si -. Je finis avec des champs statiques non finales qui pourraient être à l'extérieur ... hmmm manipulables
-
Le cadre supporte un crochet pour
C
s'initialiser instanciation après (la méthode deinitialize()
ci-dessus). Cette méthode pourrait auto-inject l'instance nouvellement créée par injection setter.
Avec 2, je suppose que cela signifie altérabilité plus externe, mais au moins la dépendance expose un peu plus explicitement pour des choses comme des tests unitaires. Le problème est: comment puis-je obtenir mes mains sur le Injector Guice dans ce cas (à court de compter sur un autre localisateur de service)? Je l'ai lu aussi (et d'accord avec) que se référant explicitement à l'injecteur à travers le code de l'application est pratique douteuse.
Votre perspicacité serait vraiment apprécié.
Merci,
Christian
La solution
Vous pouvez essayer l'injection statiquement fournisseurs dans C. injection statique plus difficile à tester. Mais les fournisseurs permettent de Guice pour valider vos dépendances avec impatience, tout en les créant paresseusement.
public class C implements I {
@Inject static Provider<Dep1> dep1Provider;
@Inject static Provider<Dep2> dep2Provider;
...
public void initialize() {
Dep1 dep1 = dep1Provider.get();
Dep2 dep2 = dep2Provider.get();
...
}
}
Autres conseils
Si vous faites votre Guice injecteur disponible par la variable statique et les méthodes accesseurs statiques vous pouvez le résoudre comme ceci:
public class C implements I {
public C() {
// this ctor is invoked by the framework, you can't do injection here.
}
public void initialize() {
MyGuice.getInjector().inject(this);
}
@Inject
protected void init(Dep1 dep1, Dep2 dep2) {
this.dep1 = dep1;
this.dep2 = dep2;
}
private void m() {
dept1.doSmth();
}
}
L'appel statique est un peu d'un anti-modèle, vous pouvez supprimer cette dépendance avec une simple annotation qui prend soin de l'injection après constructeur si vous êtes prêt à utiliser une solution qui fait le tissage de code ou d'une étape de post-compilation. De cette façon, vous pouvez injecter tous les objets même si elles ne sont pas une méthode d'initialisation. Vous pouvez trouver un exemple ici. Comment injecter modèle objet avec AspectJ
@Configurable
public class C implements I {
public C() {
// this ctor is invoked by the framework, you can't do injection here.
}
@Inject
protected void init(Dep1 dep1, Dep2 dep2) {
this.dep1 = dep1;
this.dep2 = dep2;
}
private void m() {
dept1.doSmth();
}
}