In the project I'm working on, I'm using Guice and trying to do as much as possible with Dependency Injection. However, there's one little snag; many of my objects rely on an object Context
. This is an immutable object but has some information which most of the other objects need to function properly. It never changes for classes that are all working within the same Context
, but my application must be able to support different Context
s at the same time, in the same scope. I can think of three ways to solve my problem:
Currently, I've found myself writing lots of code with AssistedInject, which almost always has methods like
Factory.create(Context c)
. All my code that depends onContext
is being created in this manner, even if they are otherwise simple.I'm starting to consider using
Provider
s, and changing every line offactory.create(context)
toobj = provider.get(); obj.setContext(c);
but I don't want to rely on my code to do both calls, I like that the compiler makes sure that every object has it'scontext
and that thecontext
cannot change (it never will).My research pointed me to this thread: https://stackoverflow.com/questions/16316719/guice-assisted-injection-deeper-down-the-dependency-hierarchy The idea of pairing each
Context
to achildInjector
which has one linebind(Context.class).toInstance(ContextFactory.makeInstance(args))
, but I'm not sure how to ensure that everything is using the correct child injector. This seems like it might be best, but other than that thread (which isn't my scenario) I'm not sure how to do it, or if it's right for my situation.
Here's an sscce of what might be done by option 3:
public class GuiceChildTest {
public static void main(String... args) {
Injector inj = Guice.createInjector(new ParentModule());
Injector fooChildOne = inj.createChildInjector(new FooModule(new Foo(10)));
Injector fooChildTwo = inj.createChildInjector(new FooModule(new Foo(20)));
Bar bar = fooChildOne.getInstance(Bar.class);
System.out.println(bar.baz());
bar = fooChildTwo.getInstance(Bar.class);
System.out.println(bar.baz());
}
private static class ParentModule extends AbstractModule {
@Override
protected void configure() {
}
}
private static class Bar {
private MyInterface intf;
@Inject
public Bar(MyInterface in) {
this.intf = in;
}
public int baz() {
return intf.doSomething();
}
}
private static class FooModule extends AbstractModule {
private Foo f;
public FooModule(Foo f) {
this.f = f;
}
@Override
protected void configure() {
bind(MyInterface.class).toInstance(f);
}
}
private static class Foo implements MyInterface {
private int i;
public Foo(int i) {
this.i = i;
}
@Override
public int doSomething() {
return i;
}
}
private static interface MyInterface {
int doSomething();
}
}