Reputation: 7023
From what I understand Guice supports injection for: Constructors, Setters (which they call method injection for some reason), fields.
Can it also inject method parameters? For example:
void foo(InterfaceA a, InterfaceA a1){
...
}
interface InterfaceA{
...
}
class A implements InterfaceA{
....
}
class B implements InterfaceA{
....
}
I want to be able to bind a
in foo
to type A
and a1
to B
(will probably need annotation but lets ignore that for a second).
I want this to be done on invocation.
This seems different from the normal use cases (c'tor, fields, setters) in the sense that the dependency injection will happen on invocation rather than on object creation.
So is this possible?
Upvotes: 3
Views: 6730
Reputation: 95614
Vladimir's answer is correct, but rather than injecting the injector, you can use field injection and Providers to do the same more concisely and to check that dependencies are satisfied at injector creation time. This code is the same as his, but modified to use Providers:
Injector injector = Guice.createInjector(b -> {
b.bind(InterfaceA.class).annotatedWith(Names.named("a")).to(A.class);
b.bind(InterfaceA.class).annotatedWith(Names.named("a1")).to(B.class);
b.bind(Invoke.class);
});
public class Invoke {
// Constructor injection works too, of course. These fields could also be
// made private, but this could make things difficult to test.
@Inject @Named("a") Provider<InterfaceA> aProvider;
@Inject @Named("a1") Provider<InterfaceA> a1Provider;
public void invoke() {
this.foo(aProvider.get(), a1Provider.get());
}
void foo(InterfaceA a, InterfaceA a1){
...
}
}
Upvotes: 6
Reputation: 127761
Well, you can do this:
Injector injector = Guice.createInjector(b -> {
b.bind(InterfaceA.class).annotatedWith(Names.named("a")).to(A.class);
b.bind(InterfaceA.class).annotatedWith(Names.named("a1")).to(B.class);
b.bind(Invoke.class);
});
public class Invoke {
private final Injector injector;
@Inject
Invoke(Injector injector) {
this.injector = injector;
}
public void invoke() {
this.foo(
injector.getInstance(Key.get(InterfaceA.class, Names.named("a"))),
injector.getInstance(Key.get(InterfaceA.class, Names.named("a1")))
);
}
void foo(InterfaceA a, InterfaceA a1){
...
}
}
But nothing more. Guice is a dependency injection framework and it usually means "construct objects with all their dependencies". While method parameters are dependencies formally (since the class is supposed to use them - this is the definition of dependency), they are not usually regarded as those by DI frameworks. It is understandable - this would make these frameworks much more complex for little to no gain, and also Java is not expressive enough language for such things not to look obscenely ugly.
Upvotes: 3