2013-06-07 12 views
5

Mam następujący kod za pomocą wiązań Guice:Guice: Wiązanie kilku obiektów z różnymi zależnościami

public class MyApplication { 
    public static void main(String[] args) { 
     Guice.createInjector(new AbstractModule() { 
      @Override 
      protected void configure() { 
       bind(Foo.class).annotatedWith(Names.named("first")).toInstance(new Foo("firstFoo")); 
       bind(Foo.class).annotatedWith(Names.named("second")).toInstance(new Foo("secondFoo")); 

       bind(Bar.class).to(BarImpl.class); 

       bind(MyApplication.class).asEagerSingleton(); 
      } 
     }); 
    } 

    private @Named("first") Bar first; 
    private @Named("second") Bar second; 

    static @Value class Foo { String name; } 
    static interface Bar {} 

    static class BarImpl implements Bar { 
     @Inject @Named Foo foo; 
    } 
} 

próbuję dostać Bar obiekt dla obu wymienionych Foo s wstrzykiwane w mojej aplikacji. Zasadniczo powinien jakoś połączyć @Named na Foo z tym na Bar. Wypróbowałem kilka rozwiązań, od umieszczenia @Named na wszystkim, aż po napisanie niestandardowego Provider. Ten ostatni nie działał, ponieważ nie mam dostępu do wartości adnotacji @Named wewnątrz dostawcy. Myślę, że rozwiązanie jest gdzieś w linii bind(Bar.class).to(BarImpl.class);, nakazujące zapamiętać wartość adnotacji @Named.

Moje pytanie brzmi, czy to w ogóle możliwe, a jeśli tak, to w jaki sposób?

Odpowiedz

10

Używa się PrivateModules. Zasadniczo:

Informacje o konfiguracji modułu prywatnego są domyślnie ukryte przed środowiskiem. Tylko połączenia, które są jawnie naświetlone, będą dostępne dla innych modułów i dla użytkowników wtryskiwacza. Więcej objaśnienia znajduje się pod adresem this FAQ entry.

Oto jak chcesz go używać:

protected void configure() { 
    install(new PrivateModule() { 
     @Override 
     protected void configure() { 
      // #bind makes bindings internal to this module unlike using AbstractModule 
      // this binding only applies to bindings inside this module 
      bind(Foo.class).toInstance(new Foo("first")); 
      // Bar's foo dependency will use the preceding binding 
      bind(Bar.class).annotatedWith(Names.named("first")).to(BarImpl.class); 
      // if we'd stop here, this would be useless 
      // but the key method here is #expose 
      // it makes a binding visible outside as if we did AbstractModule#bind 
      // but the binding that is exposed can use "private" bindings 
      // in addition to the inherited bindings    
      expose(Bar.class).annotatedWith(Names.named("first")); 
     } 
    }); 
    install(new PrivateModule() { 
     @Override 
     protected void configure() { 
      bind(Foo.class).toInstance(new Foo("second")); 
      bind(Bar.class).annotatedWith(Names.named("second")).to(BarImpl.class); 
      expose(Bar.class).annotatedWith(Names.named("second")); 
     } 
    }); 
     bind(MyApplication.class).asEagerSingleton(); 
    } 
} 

Teraz można skutecznie mieć 2 bary, z których każdy wyglądają jak

static class BarImpl implements Bar { 
    @Inject Foo foo; 
} 

ale z mocą PrivateModules mają inną realizację związanego z ta sama zależność.

Mam nadzieję, że to ma sens.

+0

Dzięki, to wygląda obiecująco. Wypróbuję to w poniedziałek. – Jorn

+1

Tak, to rozwiązało mój problem. Dzięki jeszcze raz! – Jorn

+0

Nie ma za co! –

Powiązane problemy