Suppose I have a third party class as follows:
public class MyObject {
@Inject
public MyObject(Foo foo, Bar bar) { ... }
}
Now suppose that I have a factory interface like so:
public interface MyObjectFactory {
public MyObject build(Bar bar);
}
The idea is that I wish to have a MyObjectFactory
that builds a MyObject
for a fixed Foo
- that is, essentially adding in the @Assisted
annotation on the Bar
constructor parameter from the outside. Of course, manually implementing MyObjectFactory
is always possible:
public class MyObjectFactoryImpl implements MyObjectFactory {
@Inject private Provider<Foo> foo;
@Override
public MyObject build(Bar bar) { return new MyObject(foo.get(), bar); }
}
But let's say that there are conditions that require me to have Guice build MyObject
instances - for example, method interceptors. This seems like a job for "injecting the injector":
public class MyObjectFactoryImpl implements MyObjectFactory {
@Inject private Injector injector;
@Override
public MyObject build(Bar bar) {
Injector child = injector.createChildInjector(new AbstractModule() {
@Override
protected void configure() {
bind(Bar.class).toInstance(bar);
// Set up method interceptors for MyObject here...
}
});
return child.getInstance(MyObject.class);
}
}
This sounds evil and boiler-plate-y, so I'm wondering if there are any alternate implementations and/or a way to have Guice generate the factory impl.
First of all, it is rare that you want to be passing instances of
MyObject
around in your class for exactly the reasons you describe. You have no control over them, so you can't add@Assisted
annotations, you can't add method interceptors, etc. etc. Plus, what happens when you want to swap out the third party library for a different implementation?Therefore, you should be wrapping
MyObject
into another object.Then, remove all references to
MyObject
throughout your code, using the naming convention I describe above, there should only be references toMyWrapperInterface
.