2009-08-03 10 views
11

puoi ottenere 2 istanze singleton dello stesso tipo sottostante?Ottenere più singleton a piacere dello stesso tipo

questo è ovviamente banale in quanto è basato su istanze denominate a cui si allega un ambito ma non riesco a vedere l'equivalente in guice che riguarda i tipi di binding per le classi di implementazione. Si noti che non desidero dovere associare all'istanza poiché le istanze in questione vengono iniettate da altre dipendenze.

risposta

15

Anche a Guice è facile! Creare due annotazioni di aspettare, dire @One e @Two e poi

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

e poi

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

o un metodo @Provides se ha le dipendenze, ho perso questo po 'di docs (http://code.google.com/docreader/#p=google-guice&s=google-guice&t=ProvidesMethods) dipendenze possono essere passati come parametri al metodo. L'iniettore eserciterà le associazioni per ognuno di questi prima di invocare il metodo. – Matt

+0

Non è necessario associarlo a un'istanza. Due diverse annotazioni alla stessa classe, in ambito singleton, creeranno già due istanze separate. –

+2

@Filip, ho provato quello che stai suggerendo e ho ricevuto la stessa istanza per entrambe le annotazioni. Ho usato '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

mi piacerebbe completare la risposta di Marcin, aggiungendo che non è necessario limitarsi ad usare toInstance() o metodi di provider in tale situazione.

Quanto segue funziona altrettanto bene:

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 inietta le dipendenze come al solito quando si crea un'istanza delle classi Marty McFly e DocBrown.


Nota che funziona anche quando si desidera associare più single della stesso tipo:

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

Per far funzionare tutto questo, è necessario assicurarsi che Person non è vincolato in Singleton ambito, esplicitamente nel modulo Guice o con l'annotazione . Maggiori dettagli in this Gist.

Modifica: Il codice di esempio che fornisco come esempio proviene da Guice Grapher Test. Guardare i test di Guice è un ottimo modo per capire meglio come usare l'API (che si applica anche ad ogni progetto con buoni test unitari).

+1

Mi piace l'esempio –

+0

Grazie Jesse :) Il codice di esempio che ho utilizzato per illustrare il mio punto in realtà proviene da un test per l'estensione Guice Grapher. Ho pensato che fosse divertente e l'ho incollato così com'è. Avrei dovuto mettere un link alla fonte, però (lo farò adesso). Per inciso, adoro il tuo blog e in particolare i tuoi articoli pratici su Guice/Google Collections (http://publicobject.com/). Abbiamo bisogno di più blog come il tuo. Quindi, grazie anche per questo. –

+0

@eneveu, suggerisci che la tua soluzione è un'alternativa a quella di Marcin. Mi sembra che il caso d'uso che descrivi sia diverso dal suo, perché il tuo assume che ci siano due diverse classi di implementazione del driver (MartyMcFly, DocBrown), a differenza di due istanze di una classe concreta (Driver). Quando provo a usare questa tecnica in quest'ultimo caso, ottengo due riferimenti allo stesso singleton usando questo: 'bind (MySingleton.class) .annotatedWith (One.class) .to (MySingleton.class) .in (Singleton.class); bind (MySingleton.class) .annotatedWith (Two.class) .to (MySingleton.class) .in (Singleton.class); ' –

Problemi correlati