2010-10-21 13 views
12

C'è qualcosa che non capisco in giro: secondo quello che ho letto fino ad ora, dovrei usare l'iniettore solo nella mia classe bootstrap (in un'applicazione standalone questo sarebbe tipicamente nella main() metodo), come nell'esempio seguente (preso dalla documentazione Guice):Come evitare di avere injector.createInstance() dappertutto quando si usa guice?

public static void main(String[] args) { 
    /* 
    * Guice.createInjector() takes your Modules, and returns a new Injector 
    * instance. Most applications will call this method exactly once, in their 
    * main() method. 
    */ 
    Injector injector = Guice.createInjector(new BillingModule()); 

    /* 
    * Now that we've got the injector, we can build objects. 
    */ 
    RealBillingService billingService = injector.getInstance(RealBillingService.class); 
    ... 
    } 

Ma cosa succede se non tutti gli oggetti che io abbia mai bisogno può essere creato durante l'avvio? Forse voglio rispondere ad alcune interazioni con l'utente quando l'applicazione è in esecuzione? Non devo tenere il mio iniettore da qualche parte (ad esempio come variabile statica) e quindi chiamare injector.getInstance (SomeInterface.class) quando ho bisogno di creare un nuovo oggetto?

Naturalmente la diffusione di chiamate a Injector.getInstance() in tutto il luogo sembra non essere desiderabile.

Cosa sto sbagliando qui?

risposta

12

Sì, in pratica è sufficiente utilizzare l'iniettore per creare l'istanza per l'oggetto radice. Il resto dell'applicazione non dovrebbe toccare il contenitore Guice. Come hai notato, devi comunque creare alcuni oggetti quando richiesto. Ci sono diversi approcci per farlo, ognuno adatto a diverse esigenze.

Inject a Provider Provider è un'interfaccia di Guice. Ti permette di richiedere una nuova istanza di un oggetto. Questo oggetto verrà creato usando Guice. Per esempio.

class MyService{ 
    private Provider<Transaction> transactionProvider; 
    public MainGui(Provider<Transaction> transactionProvider){ 
     this.transactionProvider = transactionProvider; 
    } 

    public void actionStarted(){ 
     Transaction transaction = transactionProvider.get(); 
    } 

costruire una fabbrica Spesso è necessario un qualche tipo di fabbrica. Questa fabbrica utilizza alcuni servizi iniettati e alcuni parametri e crea un nuovo oggetto per te. Quindi usi questa fabbrica per nuove istanze. Quindi iniettare quella fabbrica e usarla. C'è anche un aiuto per questo con il AssistedInject -estensione

Penso che con queste due possibilità raramente è necessario utilizzare il Guice-Injector stesso. Tuttavia a volte è ancora appropriato utilizzare l'iniettore stesso. Quindi è possibile iniettare l'iniettore su un componente.

3

Per estendere la risposta su Gamlor, è necessario anche differenziare tra i tipi di oggetto che si stanno utilizzando.

Per i servizi, l'iniezione è la soluzione corretta, tuttavia, non tentare di rendere sempre iniettabili gli oggetti dati (che in genere sono le foglie nel grafico degli oggetti). Ci possono essere situazioni in cui questa è la soluzione corretta, ma l'iniezione di una Provider<List> probabilmente non è una buona idea. Un mio collega ha finito per farlo, ha reso il codice base molto confuso dopo un po '. Abbiamo appena finito di pulire tutto e ora i moduli Guice sono molto più specifici.

+0

Sì, sono completamente d'accordo. – Gamlor

0

In astratto, penso che l'idea generale è che se rispondere a eventi utente fa parte delle capacità della vostra applicazione, poi, beh ...

BillingService billingService = injector.getInstance(BillingService.class); 
billingService.respondToUserEvent(event); 

immagino che potrebbe essere un po 'astratto , ma l'idea di base è quella di ottenere da Guice la tua classe di applicazione di alto livello. A giudicare dalla tua domanda, suppongo che forse BillingService non sia la tua classe di alto livello?

Problemi correlati