2010-01-19 16 views
53

Czy można powiedzieć Guice, aby wywołała jakąś metodę (tj. Init()) po zainicjowaniu obiektu danego typu przez ?Metoda inicjacji wywołania Guice po zainicjowaniu obiektu

patrzę na funkcjonalność podobną do @PostConstruct adnotacji w EJB 3.

+0

niestety, wygląda na to autorzy Guice nie mają zamiaru dodawać @PostConstruct https://github.com/google/guice/issues/62#issuecomment-115452493, który ma silnie ogranicza stosowalność Guice (istnieją rozwiązania, ale te są dość szczegółowe). Możesz zajrzeć do innych frameworków, takich jak Spring lub JEE CDI (np. Weld). – arcuri82

Odpowiedz

28

Faktycznie, jest to możliwe. Aby uzyskać funkcjonalność, należy zdefiniować TypeListener. Coś wzdłuż linii następujących w definicji modułu:

bindListener(Matchers.subclassesOf(MyInitClass.class), new TypeListener() { 
    @Override 
    public <I> void hear(final TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) { 
     typeEncounter.register(new InjectionListener<I>() { 
      @Override 
      public void afterInjection(Object i) { 
       MyInitClass m = (MyInitClass) i; 
       m.init(); 
      } 
     }); 
    } 
}); 
+4

Możesz także użyć GuicyFruit, który twierdzi, że wspiera @PostConstruct (zobacz http://code.google.com/p/guiceyfruit /), i chociaż nie odpowiada na to pytanie, myślę, że warto wspomnieć, że jeśli (wyłącznie) korzystasz z wtrysku konstruktora, nie potrzebujesz takiej funkcjonalności, jak możesz wykonać całą inicjalizację w konstruktorze. – Eelco

+0

zapisał mój dzień. @PostConstruct nie jest obsługiwany przez guiceyfruit jeszcze –

+7

Matchers.subclassesOf (MyInitClass.class) faktycznie spowoduje błąd podczas kompilacji: "Metoda bindListener (Matcher >, TypeListener) w typie AbstractModule nie ma zastosowania dla argumentów (Matcher , nowy TypeListener() {}) " Myślę, że będziesz musiał przedłużyć AbstractMatcher, aby twój kod działał – Andrey

6

guiceyfruit robi to, co jesteś po metod opatrzone @PostConstruct lub wykonawczych sprężyny InitializingBean. Możliwe jest również napisanie własnych słuchaczy, aby to zrobić. Oto przykład, który wywołuje publiczną metodę init() po utworzeniu obiektów.

import com.google.inject.*; 
import com.google.inject.matcher.*; 
import com.google.inject.spi.*; 

public class MyModule extends AbstractModule { 
    static class HasInitMethod extends AbstractMatcher<TypeLiteral<?>> { 
    public boolean matches(TypeLiteral<?> tpe) { 
     try { 
     return tpe.getRawType().getMethod("init") != null; 
     } catch (Exception e) { 
     return false; 
     } 
    } 

    public static final HasInitMethod INSTANCE = new HasInitMethod(); 
    } 

    static class InitInvoker implements InjectionListener { 
    public void afterInjection(Object injectee) { 
     try { 
     injectee.getClass().getMethod("init").invoke(injectee); 
     } catch (Exception e) { 
     /* do something to handle errors here */ 
     } 
    } 
    public static final InitInvoker INSTANCE = new InitInvoker(); 
    } 

    public void configure() { 
    bindListener(HasInitMethod.INSTANCE, new TypeListener() { 
     public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) { 
     encounter.register(InitInvoker.INSTANCE); 
     } 
    }); 
    } 
} 
+0

Dzięki za miły przykład, zastanawiam się, czy getMethod ("") kiedykolwiek zwróci wartość null, ponieważ gdy nie znajdzie określonej metody, generuje NoSuchMethodException, a javadoc również tego nie komentuje. – zeratul021

49

Możesz po prostu dodać adnotację @Inject do swojej metody init(). Uruchomi się automatycznie po utworzeniu obiektu.

+9

Problem w tym, że to podejście nie działa, jeśli masz opcjonalne zależności, ponieważ nie ma sposobu, aby powiedzieć guice, aby wywołać twoją metodę init() jako ostatnią metodę, o ile wiem. IMHO potrzebują wsparcia @PostConstruct. –

+0

Korzystam z wtrysku konstruktora, gdzie muszę wykonać pewne czynności inicjujące, które zależą od innych zależności. –

+1

@ OrtwardenAngermeier, jeśli dobrze cię rozumiem, możesz umieścić adnotację '@ Inject' na swoim konstruktorze _ i _ na swojej metodzie init. –

Powiązane problemy