2015-05-18 8 views
5

Non ho mai usato guice prima, e volevo provarlo su un progetto di esempio con l'API JAX-RS basata su jersey supportata da un bean di servizio. Ho seguito questa guida: http://randomizedsort.blogspot.de/2011/05/using-guice-ified-jersey-in-embedded.html e sono riuscito a farlo funzionare. La mia configurazione è molto semplice, una risorsa JAX-RS viene chiamata tramite Guice e ha un campo che è annotato @Inject e iniettato da Guice:auto scan for guice

@Path("configuration") 
@Produces(MediaType.APPLICATION_JSON) 
@Singleton 
public class ConfigurationResource { 

    @Inject 
    private ConfigurationService configurationService; 

Fin qui tutto bene, tutto funziona come dovrebbe, oltre a seguire: sto usando GuiceServletContextListener per impostare le cose e devo nominare ogni componente in modo esplicito:

@WebListener 
public class GuiceInitializer extends GuiceServletContextListener{ 
    @Override 
    protected Injector getInjector() { 
     return Guice.createInjector(new JerseyServletModule() { 
      @Override 
      protected void configureServlets() { 
       //resources 
       bind(ConfigurationResource.class); 

       //services 
       bind(ConfigurationService.class).to(ConfigurationServiceImpl.class); 

       // Route all requests through GuiceContainer 
       serve("/management/*").with(GuiceContainer.class); 
      } 
     }); 
    } 
} 

trovo abbastanza scomodo per citarne esplicitamente tutte le dipendenze. Ho già lavorato con la maglia standalone ed è perfettamente in grado di eseguire la scansione automatica delle risorse in pacchetti definiti. Anche Spring e CDI sono in grado di mappare l'implementazione alle interfacce senza bisogno di nominarle esplicitamente.

Ora la parte domanda:

  • v'è alcuna estensione scansione automatica/impostazione Guice? Ne ho trovati su internet, ma è difficile dire quali di questi sono ancora utilizzabili e aggiornati.

  • c'è qualche altra possibilità per rendere più conveniente la configurazione di implementazioni e risorse?

grazie in anticipo. Leon

+1

Auto -scanning incoraggia gli sviluppatori ad aggiungere solo dipendenze. Uno dei motivi per cui Guice mi piace è che, a differenza di Spring, ogni volta che aggiungi una dipendenza, sei costretto a chiedertelo "Questa dipendenza ha senso? È davvero necessario? Sto facendo troppo con questa lezione?" –

+1

Ciao @ jerry-andrews, e grazie per il commento. Forse sto un po 'fraintendendo Guice. Volevo usare Guice come possibilità di usare la semantica javax.inject senza il gonfiore di ejb/cdi o spring. Inoltre, penso al tuo commento, che se sto scrivendo una classe di risorse, annotandolo @ Path e @ GET e cosa no, e implementando la logica dietro di loro, ho già risposto alla domanda "questa risorsa ha senso", ed essere costretti ad aggiungerlo a un modulo di configurazione è solo una fonte di errori stupidi ... – Leon

+0

Si potrebbe voler utilizzare l'hk2 per questo, è possibile eseguire la scansione delle classi in fase di compilazione con [hk2-metadata-generator] (https : //hk2.java.net/2.4.0-b24/inhabitant-generator.html) e quindi puoi usare il [ponte hk2] (https://hk2.java.net/2.4.0-b24/apidocs/ org/glassfish/hk2/extra/ExtrasUtilities.html # bridgeServiceLocator% 28org.glassfish.hk2.api.ServiceLocator,% 20org.glassfish.hk2.api.ServiceLocator% 29) per integrarlo con Jersey ServiceLocator – jwells131313

risposta

3

Non credo che Guice abbia creato un supporto per qualcosa come la scansione dei componenti del framework Spring. Tuttavia, non è difficile simulare questa funzionalità in Guice.

Hai semplicemente bisogno di scrivere un modulo helper come il seguente

import com.google.inject.AbstractModule; 
import org.reflections.Reflections; 

import java.lang.annotation.Annotation; 
import java.util.Arrays; 
import java.util.HashSet; 
import java.util.Set; 

/** 
* To use this helper module, call install(new ComponentScanModule("com.foo", Named.class); in the configure method of 
* another module class. 
*/ 
public final class ComponentScanModule extends AbstractModule { 
    private final String packageName; 
    private final Set<Class<? extends Annotation>> bindingAnnotations; 

    @SafeVarargs 
    public ComponentScanModule(String packageName, final Class<? extends Annotation>... bindingAnnotations) { 
     this.packageName = packageName; 
     this.bindingAnnotations = new HashSet<>(Arrays.asList(bindingAnnotations)); 
    } 

    @Override 
    public void configure() { 
     Reflections packageReflections = new Reflections(packageName); 
     bindingAnnotations.stream() 
      .map(packageReflections::getTypesAnnotatedWith) 
      .flatMap(Set::stream) 
      .forEach(this::bind); 
    } 
} 

Per componente eseguire la scansione di un pacchetto come com.foo e pacchetti sub per le classi che trasportano @Singleton, utilizzarlo in questo modo:

public class AppModule extends AbstractModule { 
    public void configure() { 
    install(new ComponentScanModule("com.foo", Singleton.class)); 
    } 
}