2010-02-01 2 views
27

Situazione: ho bisogno di un'istanza di dipendenza lazy in alcuni FooClass, quindi passo alla classe Injector come parametro costruttore.Come iniettare iniettore?

private final Injector m_injector; 

public FooClass(@Named("FooInjector") Injector injector) { 
m_injector = injector; 
} 

Ma guinghia non consente di associare le classi principali (iniettori, moduli e così via). Qual'è la soluzione?

risposta

27

Non si dovrebbe utilizzare direttamente lo Injector. Piuttosto passare il Provider<FooClass> invece. Inoltre, dovresti iniettare il fornitore nei luoghi in cui usi FooClass.

private final Provider<FooClass> provider; 

@Inject 
public ClassWhereFooIsUsed(Provider<FooClass> provider) { 
    this.provider = provider; 
} 

.... somewhere else 
FooClass f = provider.get(); // This is lazy 
+0

Thx! Ci proverò per l'inizializzazione pigra. Ma non c'è davvero alcun modo di iniettare Injector? –

+6

È possibile ottenere l'iniettore con 'iniettore iniettore @Inject', può essere sul costruttore/campo/metodo. – gpampara

+0

Hai provato questo? Come configurare il modulo? Guice limita l'associazione alle classi core: "Non è consentito legare al tipo di framework guice principale: Injector." –

7

Come @gpampara detto, Provider<T> deve essere utilizzato per l'inizializzazione differita/opzionale. Inoltre, come ho detto nella mia risposta alla tua altra domanda, dovresti evitare di fare riferimento al codice Injector nel tuo codice in quasi tutti i casi.

Detto questo, in una classe creata da Guice, lo Injector che sta creando l'oggetto può essere iniettato solo dichiarando una dipendenza su Injector. Il Injector è automaticamente disponibile per l'iniezione senza che tu dichiari alcun legame per esso.

Se si immette il Injector, è necessario pensare a PERCHÉ si desidera farlo. Perché non dichiarate solo dipendenze dalle effettive interfacce/classi da cui dipende la classe? Aggiungere una nuova dipendenza al costruttore è altrettanto semplice quanto recuperare un'istanza di una certa dipendenza attraverso lo Injector altrove nel codice e rende il codice molto più comprensibile.

+0

Ri: "PERCHÉ lo vuoi fare?" - Ad esempio, voglio creare al volo i proxy dinamici dopo il bootstrap. la mia domanda al riguardo: http://stackoverflow.com/questions/34252268/best-practice-for-creating-dynamic-proxies-with-guice –

8

Come altri hanno già risposto, è possibile utilizzare semplicemente @ Inject Injector perché Guice definisce l'associazione stessa.

Normalmente è necessario un solo iniettore nell'app e una variabile statica è un modo ancora più semplice per archiviare e accedere a un singoletto piuttosto che iniettarlo. Nella nostra app Web, usiamo stripes-guicer e riceviamo l'iniettore dal suo metodo statico GuiceInjectorFactory.getInjector() quando ne abbiamo bisogno (nel nostro intercettore Hibernate, ad esempio).

Sono un po 'sconcertato dal consiglio che "non si dovrebbe usare l'iniettore direttamente". In quale altro modo avrei ricevuto un'istanza iniettata, tranne chiamando injector.getInstance() o injector.injectMembers()? Non c'è alcun modo. Sì, puoi definire i metodi Provider, ma non verranno mai chiamati a meno che da qualche parte, qualcosa usi un iniettore. Sì, ci sono moduli che utilizzano l'iniettore per te come il ServletModule; devi creare l'Injector da solo, ma puoi lasciarlo successivamente al ServletModule.

Quindi in alcune circostanze è possibile evitare di utilizzare direttamente l'iniettore, ma ciò non significa che non si debba "usarlo". Se stai usando Guice da solo senza moduli opzionali, allora dovresti "usare" un iniettore dappertutto perché non c'è altro modo per attivare l'iniezione. (Penso che gli sviluppatori che passano tutto il giorno a scrivere il codice all'interno dei framework a volte dimentichino che alcune persone realizzano istantaneamente i propri oggetti.)

+3

Non sono convinto di aver compreso la logica alla base di Guice. Spiega esplicitamente di evitare l'uso di campi e stati statici, e raramente si deve fare un riferimento diretto allo stesso iniettore. Ottieni istanze iniettate dichiarando dipendenze con @Inject, invece di chiamare 'getInstance()' sull'iniettore. –

+12

Il mio unico punto (che ho fatto piuttosto in modo verbale) è che devi iniziare da qualche parte; è un problema di pollo e uova. Non puoi * solo * decorare i metodi con @Inject e aspettarti che accada qualcosa. Qualcosa, da qualche parte, deve chiamare injector.getInstance() o injector.injectMembers() per avviare tutto. –