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.
// **Please** choose better names than this in your real code.
public class MyWrapperBackedByMyObject implements MyWrapperInterface {
private final MyObject delegate;
@Inject
MyWrapperObject(Foo foo, @Assisted Bar bar) {
delegate = new MyObject(foo, bar);
}
@NotOnWeekends // Example of how you might do method interception
public void orderPizza() {
delegate.orderPizza();
}
}
Then, remove all references to MyObject
throughout your code, using the naming convention I describe above, there should only be references to MyWrapperInterface
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With