Question

New to Guice, so I'm looking into its expressive power. Suppose I have classes as follows:

public class Data {
    @Inject
    public Data(@Named("First") String first, @Named("Second") String second) { ... }
}

public class DataUser1 {
    @Inject
    public DataUser1(Data data) { ... }
}

public class DataUser2 {
    @Inject
    public DataUser2(Data data) { ... }
}

How do I create a module such that when I call injector.getInstance(DataUser1.class) I get something equivalent to new DataUser1(new Data("foo", "bar")) while having injector.getInstance(DataUser2.class) I get something equivalent to new DataUser2(new Data("foo2", "bar2"))?

Also related, how do I create a module for which I may need to get two instances of DataUser1, each of which using different Data values?

Était-ce utile?

La solution

You use private modules for creating graphs of objects which are almost the same but differ in particular details.

public class DataUser1Module extends PrivateModule {
    @Override
    protected void configure() {
        bindConstant().annotatedWith(Names.named("First")).to("foo");
        bindConstant().annotatedWith(Names.named("Second")).to("bar");

        bind(Data.class);
        bind(DataUser1.class);

        expose(DataUser1.class);
    }
}

public class DataUser2Module extends PrivateModule {
    @Override
    protected void configure() {
        bindConstant().annotatedWith(Names.named("First")).to("foo2");
        bindConstant().annotatedWith(Names.named("Second")).to("bar2");

        bind(Data.class);
        bind(DataUser2.class);

        expose(DataUser2.class);
    }
}

Injector injector = Guice.createInjector(new DataUser1Module(), new DataUser2Module());
DataUser1 dataUser1 = injector.getInstance(DataUser1.class);
DataUser2 dataUser2 = injector.getInstance(DataUser2.class);

You do the same thing if you need two instances of DataUser1 with different Datas, but you use annotations to differentiate between them:

public class DataUser1Module1 extends PrivateModule {
    @Override
    protected void configure() {
        bindConstant().annotatedWith(Names.named("First")).to("foo");
        bindConstant().annotatedWith(Names.named("Second")).to("bar");

        bind(Data.class);
        bind(DataUser1.class).annotatedWith(Names.named("1")).to(DataUser1.class);

        expose(DataUser1.class).annotatedWith(Names.named("1"));
    }
}

public class DataUser1Module2 extends PrivateModule {
    @Override
    protected void configure() {
        bindConstant().annotatedWith(Names.named("First")).to("foo2");
        bindConstant().annotatedWith(Names.named("Second")).to("bar2");

        bind(Data.class);
        bind(DataUser1.class).annotatedWith(Names.named("2")).to(DataUser1.class);

        expose(DataUser1.class).annotatedWith(Names.named("2"));
    }
}

Injector injector = Guice.createInjector(new DataUser1Module1(), new DataUser1Module2());
DataUser1 dataUser11 = injector.getInstance(Key.get(DataUser1.class, Names.named("1"));
DataUser1 dataUser12 = injector.getInstance(Key.get(DataUser1.class, Names.named("2"));

This pattern is described in Guice FAQ.

See also these questions:

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top