Reputation: 83879
I have the following scenario:
public class InjectionTest {
private static class Sub {
@Inject private final String value = null;
}
private static class General {
@Inject private final Sub sub = null;
}
private static class MainOne {
@Inject private final General general = null;
}
private static class MainTwo {
@Inject private final General general = null;
}
public static void main(String... arguments) {
Injector injector = Guice.createInjector(new AbstractModule() {
@Override protected void configure() {
/* DO MAGIC */
}
});
MainOne mainOne = injector.getInstance(MainOne.class);
MainTwo mainTwo = injector.getInstance(MainTwo.class);
assertThat(mainOne.general.sub.value, is("one"));
assertThat(mainTwo.general.sub.value, is("two"));
}
}
I want the value
accessible from the instance of MainOne
to be "one"
and the value
accessible from the MainTwo
instance to be "two"
. I have tried the following:
Named
annotation; unfortunately this requires that I create the General
instances myself or use a child injectors to create the Sub
instances.Scope
mechanism. I couldn’t really get it to work the way I wanted to and got the feeling that it was never intended to do this and in fact even can not do this at all.(Of course the real scenario is more complicated, as always: I have a GuiceServletContextListener
and a ServletModule
and I’m trying to reuse a couple of classes/services among all created Servlet
instances but also need a couple of specialized modules that are requested from the servlets.)
Am I missing anything? Is there a (relatively) easy way to achieve what I want?
Upvotes: 0
Views: 202
Reputation: 2349
First off, you shouldn't inject into final fields (see comments). I suggest that you remove the final
modifier, or use constructor injection.
It's possible to solve your example by using private modules. But I don't consider this an "easy" solution.
Injector injector = Guice.createInjector(new PrivateModule() {
@Override
protected void configure() {
bind(String.class).toInstance("one");
bind(MainOne.class);
expose(MainOne.class);
}
}, new PrivateModule() {
@Override
protected void configure() {
bind(String.class).toInstance("two");
bind(MainTwo.class);
expose(MainTwo.class);
}
});
I think you're better off using either @Named
or creating your own binding annotation.
Also read the wiki page on the "robots leg" problem: https://github.com/google/guice/wiki/FrequentlyAskedQuestions#how-do-i-build-two-similar-but-slightly-different-trees-of-objects
Upvotes: 2