2009-05-23 17 views
13

Continuo a voler provare questo su una scala più grande con il nostro sistema di build + app, ma priorità più elevate continuano a spingerlo al rovescio. Sembra un bel modo per caricare i moduli Guice ed evitare il comune reclamo sulla "configurazione hard coded". Le singole proprietà di configurazione raramente cambiano da sole, ma si avrà quasi sempre un insieme di profili, solitamente per ambienti diversi (Debug, Produzione, ecc.).Qualcuno ha utilizzato ServiceLoader insieme a Guice?

ServiceLoader consente di estrarre un elenco di tutte le implementazioni definite come servizio per un determinato tipo. Mettendo questo insieme con Guice, si finisce con:

import java.util.ServiceLoader; 

import com.google.inject.AbstractModule; 
import com.google.inject.Module; 

public class ModuleLoader<M extends Module> extends AbstractModule { 

    private final Class<M> type; 

    public ModuleLoader(Class<M> type) { 
     this.type = type; 
    } 

    public static <M extends Module> ModuleLoader<M> of(Class<M> type) { 
     return new ModuleLoader<M>(type); 
    } 

    @Override 
    protected void configure() { 
     ServiceLoader<M> modules = ServiceLoader.load(type); 
     for (Module module : modules) { 
      install(module); 
     } 
    } 
} 

esempio di utilizzo (come servlet caricatore dinamico in un progetto guice-servlet):

import com.google.inject.servlet.ServletModule; 

public class ServletLoader extends GuiceServletContextListener { 
    @Override 
    protected final Injector getInjector() { 
     return Guice.createInjector(ModuleLoader.of(ServletModule.class); 
    } 
} 

I servizi (confezionato come moduli) sarebbe confezionato in file jar separati. All'interno di ogni uno si sarebbe definita la classe (es) nella meta-dati:

Within servlets.jar: META-INF/services/com.google.inject.Module 

com.example.webapps.MyServletModuleA 
com.example.webapps.MyServletModuleB 

Dal momento che usiamo Maven, pensiamo che questo sarebbe l'ideale come abbiamo potuto tirare in diverse implementazioni in fase di esecuzione tramite le dipendenze profilo. Qualcuno sta usando Guice in questo modo?

In caso contrario, sentitevi liberi di utilizzare questo esempio e vedere come funziona per voi. (ServiceLoader è supportato solo in JDK6 +)

+0

Potete essere d'aiuto? Sto provando a fare qualcosa di simile ma avendo un problema noobie con ServiceLoader? http://stackoverflow.com/questions/28983997/java-cant-get-a-working-serviceloader – tommed

risposta

3

Lo stiamo facendo quasi esattamente nel mio lavoro. Al momento siamo bloccati in java 5 a causa di alcune limitazioni interne, quindi lo facciamo in modo un po 'diverso usando Service Provider (non avendo accesso a ServiceLocator fino a java 6 come hai detto), ma essenzialmente funziona allo stesso modo.

Ricordo di aver letto da qualche parte che questo era uno dei metodi preferiti dagli sviluppatori di Guice, sebbene volessero lasciarlo aperto alla flessibilità.

1

Ho considerato questo modo già ma non l'ho usato perché avevo paura, che devo mantenere i miei moduli estremamente piccoli, perché è impossibile legare la stessa interfaccia due volte. Il mio problema è che, se voglio usare un'interfaccia/classe/enum/qualsiasi altro da un altro jar e che jar ha definito un file services/* sono fregato, perché non posso usare il contenuto del jar senza caricarlo come modulo.

Spero che la mia preoccupazione sia chiara.

0

"perché è impossibile collegare la stessa interfaccia due volte."

Questo è davvero sbagliato! Con il Multibinder di Guice c'è un modo per lavorare con diverse implementazioni della stessa interfaccia, possibilmente legate a moduli diversi.

Sono arrivato a una soluzione leggermente diversa per il carico effettivo rispetto a Mark Renouf (il suo ModuleLoader sembra davvero migliore), ma il mio post sul blog potrebbe mostrare un po 'di più sull'ambiente in cui questo approccio è applicabile (Plugin) e quale estensione i punti sono:

Guice 2.0 Multibinder + Java ServiceLoader = Plugin mechanism

Problemi correlati