2015-05-18 34 views
5

Nigdy wcześniej nie używałam guice i chciałem wypróbować to na przykładowym projekcie z opartym na jerseyach JAX-RS API wspieranym przez service-bean. Postępowałem zgodnie z tym przewodnikiem: http://randomizedsort.blogspot.de/2011/05/using-guice-ified-jersey-in-embedded.html i udało mi się go uruchomić. Moja konfiguracja jest bardzo prosta, zasób JAX-RS jest wywoływany poprzez Guice i ma pole, które jest uwagami @Inject i wstrzykuje przez Guice:auto scan for guice

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

    @Inject 
    private ConfigurationService configurationService; 

tej pory tak dobrze, wszystko działa tak jak powinien, oprócz następujących: Używam GuiceServletContextListener ustawiania rzeczy i trzeba wymienić każdy element wyraźnie:

@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); 
      } 
     }); 
    } 
} 

Uważam to dość niewygodne jawnie wymienić wszystkie zależności. Pracowałem wcześniej z samodzielną koszulką i doskonale nadaje się do automatycznego skanowania zasobów w określonych pakietach. Również Spring i CDI są w stanie mapować implementację do interfejsów bez potrzeby jawnego nadawania im nazwy.

Teraz część pytanie: ustawienie Guice

  • jest jakiś autoscan rozszerzenie /? Znalazłem trochę w Internecie, ale trudno stwierdzić, które z nich są nadal użyteczne i aktualne.

  • Czy jest jakaś inna możliwość wygodniejszej konfiguracji konfiguracji i zasobów?

z góry dzięki. Leon

+1

Auto -scanning zachęca programistów do dodawania nowych zależności. Jednym z powodów, dla których lubię Guice, jest to, że w przeciwieństwie do Springa, za każdym razem, gdy dodajesz zależność, jesteś zmuszony zadać sobie pytanie "Czy ta zależność ma sens? Czy to naprawdę konieczne? Czy robię za dużo z tą klasą?" –

+1

Witam @ jerry-andrews, i dziękuję za komentarz. Może trochę nie rozumiem Guice. Chciałem użyć Guice jako możliwości wykorzystania semantyki javax.inject bez rozdęcia ejb/cdi lub wiosny. Sądzę również, że jeśli chodzi o twój komentarz, to jeśli piszę klasę zasobów, dodając adnotację @ Path i @ GET, a co nie, i wdrażając logikę za nimi, już odpowiedziałem na pytanie "czy ten zasób ma sens", a bycie zmuszonym do dodania go do modułu konfiguracyjnego jest po prostu źródłem głupich błędów ... – Leon

+0

Możesz zajrzeć do tego używając hk2, może skanować twoje klasy w czasie kompilacji za pomocą [hk2-metadata-generator] (https : //hk2.java.net/2.4.0-b24/inhabitant-generator.html), a następnie możesz skorzystać z [mostu hk2] (https://hk2.java.net/2.4.0-b24/apidocs/ org/glassfish/hk2/dodatki/ExtrasUtilities.html # bridgeServiceLocator% 28org.glassfish.hk2.api.ServiceLocator,% 20org.glassfish.hk2.api.ServiceLocator% 29) w celu zintegrowania go z usługą Jersey ServiceLocator – jwells131313

Odpowiedz

3

Nie sądzę, że Guice ma wbudowane wsparcie dla czegoś podobnego do skanowania komponentów Spring Framework. Jednak nie jest trudno symulować tę funkcję w Guice.

Wystarczy napisać moduł pomocnika jak następuje

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); 
    } 
} 

do składnika zeskanować pakiet jak com.foo i paczek sub dla klas posiadających @Singleton, użyj go w ten sposób:

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