2010-08-04 19 views
10

Ho una classe in questo modo, che creo io da qualche parte nel mio codice:Guice Iniettare campo in classe non creato da Guice

class StarryEyes { 
    @Inject MyValidator validator; 

    public StarryEyes(String name) { 
     //.. 
    } 

    public doSomething() { 
     // validator is NULL 
    } 
} 

voglio Guice per iniettare un'istanza di validatore, che ha un @Singleton annotazione. Ho un modulo che è caricato in fase di avvio e contiene la linea:

bind(MyValidator.class); 

Tuttavia, non sembra funzionare come "validator" è sempre nullo. Ho provato una serie di variazioni come:

bind(MyValidator.class)toInstance(new MyValidator()); 

o altre cose del genere. Non è questo il modo in cui Guice dovrebbe funzionare?

risposta

33

In genere Guice deve creare oggetti per iniettarli. Se chiami semplicemente new StarryEyes(name), Guice non vedrà mai quell'oggetto quindi non sarà in grado di iniettarlo. Una cosa che puoi fare è chiamare injector.injectMembers(obj) sull'oggetto dopo averlo creato. Non lo consiglierei, tuttavia, poiché dovresti evitare di fare riferimento all'iniettore nel tuo codice.

Quello che davvero vorresti qui è Assisted Inject. Con Assisted Inject, che ci si dichiara il costruttore per la classe di qualcosa di simile:

@Inject public StarryEyes(MyValidator validator, @Assisted String name) 

Ciò significa che validator è un parametro che dovrebbe iniettare Guice, mentre name deve essere "assistiti" (vale a dire, a condizione al momento della creazione dell'istanza).

È quindi creare un'interfaccia simile a questo:

public interface StarryEyesFactory { 
    StarryEyes create(String name); 
} 

Con Assisted Inject, Guice può quindi implementare quella fabbrica per voi. Si associa in questo modo:

bind(StarryEyesFactory.class).toProvider(
    FactoryProvider.newFactory(StarryEyesFactory.class, StarryEyes.class)); 

È quindi iniettare una StarryEyesFactory ovunque si desidera creare un'istanza di esso. Dove avresti chiamato in precedenza new StarryEyes(name), ora devi chiamare starryEyesFactory.create(name). Quando chiami create(name) in fabbrica, prenderà il nome e lo passerà al costruttore e fornirà lo stesso validatore associato.

A partire dal 3 Guice, si esegue questa operazione utilizzando un FactoryModuleBuilder:

install(new FactoryModuleBuilder().build(StarryEyesFactory.class));