2013-06-07 1 views
5

je le code suivant à l'aide des liaisons Guice:Guice: Reliure plusieurs objets avec dépendances différentes

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

J'essaie d'obtenir un objet Bar pour les deux nommés Foo s injectés dans ma demande. Fondamentalement, il devrait en quelque sorte connecter le @Named sur Foo avec celui sur Bar. J'ai essayé plusieurs solutions, de mettre @Named sur tout à l'écriture d'un Provider personnalisé. Ce dernier n'a pas fonctionné car je n'ai pas accès à la valeur de l'annotation @Named dans le fournisseur. Je pense que la solution est quelque part dans la ligne bind(Bar.class).to(BarImpl.class);, lui disant de se souvenir de la valeur de l'annotation @Named.

Ma question est, est-ce possible du tout, et si oui, comment?

Répondre

10

Il utilise PrivateModules. Fondamentalement:

Les informations de configuration d'un module privé sont masquées par défaut dans son environnement. Seules les liaisons explicitement exposées seront disponibles pour les autres modules et pour les utilisateurs de l'injecteur. Pour plus d'explications, voir this FAQ entry.

Voici comment vous l'utiliser:

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

Maintenant, vous avez effectivement 2 bars dont chacun ressembler

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

mais avec la puissance de PrivateModules ont une implémentation différente à destination la même dépendance.

Espérons que cela a du sens.

+0

Merci, cela semble prometteur. Je vais essayer le lundi. – Jorn

+1

Oui, cela a résolu mon problème. Merci encore! – Jorn

+0

De rien! –

Questions connexes