2009-08-03 9 views
11

pouvez-vous obtenir 2 instances singleton du même type sous-jacent?Obtenir plusieurs singletons de même type

Ceci est évidemment trivial au printemps car il est basé sur des instances nommées auxquelles vous attachez une portée mais je ne peux pas voir l'équivalent dans guice qui concerne les types de liaison aux classes d'implémentation. Notez que je ne veux pas avoir à lier à l'instance car les instances en question sont injectées avec d'autres dépendances par guice.

Répondre

15

C'est aussi facile avec Guice! Créer deux annotations Biding, dites @One et @Two puis

bind(MySingleton.class).annotatedWith(One.class).toInstance(new MySingleton()); 
bind(MySingleton.class).annotatedWith(Two.class).toInstance(new MySingleton()); 

puis

@Inject 
public SomethingThatDependsOnSingletons(@One MySingleton s1, 
    @Two MySingleton t2) { ... } 
+0

ou une méthode @Provides si elle a des dépendances, j'ai raté ce bit de la documentation (http://code.google.com/docreader/#p=google-guice&s=google-guice&t=ProvidesMethods) dépendances peuvent être passé en tant que paramètres de la méthode. L'injecteur va exercer les liaisons pour chacun d'entre eux avant d'invoquer la méthode. – Matt

+0

Vous n'avez pas besoin de le lier à une instance. Deux annotations différentes à la même classe, dans la portée singleton, créeront déjà deux instances distinctes. –

+2

@Filip, j'ai essayé ce que vous suggérez, et j'ai reçu la même instance pour les deux annotations. J'ai utilisé 'bind (MySingleton.class) .annotatedWith (One.class) .to (MySingleton.class) .in (Singleton.class); bind (MySingleton.class) .annotatedWith (Two.class) .to (MySingleton.class) .in (Singleton.class); ' –

13

Je voudrais compléter la réponse de Marcin, en ajoutant que vous ne devez pas vous limiter à l'utilisation toInstance() ou les méthodes du fournisseur dans une telle situation.

Ce qui suit fonctionnera tout aussi bien:

bind(Person.class).annotatedWith(Driver.class).to(MartyMcFly.class).in(Singleton.class); 
bind(Person.class).annotatedWith(Inventor.class).to(DocBrown.class).in(Singleton.class); 

[...]

@Inject 
public BackToTheFuture(@Driver Person marty, @Inventor Person doc) { ... } 

Guice injectera les dépendances, comme d'habitude lors de l'instanciation des classes et DocBrown Marty McFly.


Notez que cela fonctionne également lorsque vous souhaitez lier plusieurs singletons du même type:

bind(Person.class).annotatedWith(Driver.class).to(Person.class).in(Singleton.class); 
bind(Person.class).annotatedWith(Inventor.class).to(Person.class).in(Singleton.class); 

Pour que cela fonctionne, vous devez vous assurer que Person est pas lié dans le Singleton portée, soit explicitement dans le module Guice, soit avec l'annotation @Singleton. Plus de détails en this Gist.

Édition: L'exemple de code que je donne comme exemple provient d'un Guice Grapher Test. Regarder les tests de Guice est un excellent moyen de mieux comprendre comment utiliser l'API (qui s'applique également à tous les projets avec de bons tests unitaires).

+1

J'aime l'exemple –

+0

Merci Jesse :) L'exemple de code que j'ai utilisé pour illustrer mon point de vue vient d'un test pour l'extension Guice Grapher. Je pensais que c'était drôle et je l'ai collé tel quel. J'aurais dû mettre un lien vers la source, (je le ferai tout de suite). En aparté, j'adore votre blog et surtout vos articles pratiques sur Guice/Google Collections (http://publicobject.com/). Nous avons besoin de plus de blogs comme le vôtre. Donc, merci pour cela aussi. –

+0

@eneveu, vous suggérez que votre solution soit une alternative à Marcin. Il me semble que le cas d'utilisation que vous décrivez est différent du sien, car le vôtre suppose qu'il existe deux classes d'implémentation de pilote différentes (MartyMcFly, DocBrown), par opposition à deux instances d'une classe concrète (Driver). Lorsque j'essaie d'utiliser cette technique dans ce dernier cas, j'obtiens deux références au même singleton en utilisant ceci: 'bind (MySingleton.class) .annotatedWith (One.class) .to (MySingleton.class) .in (Singleton.class) Bind (MySingleton.class) .annotatedWith (Two.class) .to (MySingleton.class) .in (Singleton.class); ' –