Reputation: 2549
I just started using Guice so my understanding could be completely wrong.
I have an interface Foo
and an implmentation FooImp
I have used the following code in my module to inject it:
bind(Foo.class).annotatedWith("Foo").toInstance(foo); // foo is an instance of FooImp
Then I guess now in my code wherever a Foo
instance with a name annotation of "Foo" will be replaced by foo
?
@Named("Foo")
Foo fooInst; // fooInst will be foo at runtime?
If I'm right, how can I achieve this:
public Foo doSomething() { // for some reason there must be no arguments
@Named("Foo")
Foo fooInst; // injecting here seems not allowed...?
fooInst.do();
}
Upvotes: 1
Views: 1757
Reputation: 95614
The other answers are correct--you can only inject into the constructor, or into a field. It's standard practice to keep the instances as fields, which also allows you to swap in your own implementations for testing.
If you need to produce a new instance every time a method is called, you can use a Provider
. For any given binding for Foo
(or @Baz Foo
), Provider<Foo>
(or @Baz Provider<Foo>
) is bound automatically without any extra code needed.
public class Bar {
private Provider<Foo> fooProvider;
@Inject
public Bar(@Named("foo") Provider<Foo> fooProvider) {
this.fooProvider = fooProvider;
}
public doSomething() {
Foo foo = fooProvider.get();
}
}
Of course, the way you have it with bind(...).toInstance(...)
, it will always be the same instance anyway, but should you need a new instance for every run of a method this is your best choice.
Upvotes: 0
Reputation: 869
What you are assuming is not completely right: Guice is used for dependency injection, which means that you can inject some interface/class into the constructor of another class.
Lets say you have an interface Foo
and it's implementation FooImpl
. Then you also have a class Bar
which depends on an implementation of Foo
.
public class Bar {
private Foo foo;
@Inject
public Bar(@Named("foo") Foo foo) {
this.foo = foo;
}
//some other methods
}
In your Guice-module you have to write
bind(Foo.class).annotatedWith(Names.named("Foo")).toInstance(foo);
//let's say this is part of the module MyModule extends AbstractModule
Once you set this up, you can make a main-method where you create an object by using Guice's Injector
-class. Like so:
Injector injector = Guice.createInjector(new MyModule());
Bar bar = injector.getInstance(Bar.class);
//do something with bar
Hope this helped you with it. If you have more questions, feel free to ask me!
Hint: check the website of Guice, watch the video overthere and read the wiki carefully. Guice is a really great tool, but you need to do some study before you use it. Good luck!
Addition: In my opinion using @Named
is a bad codestyle. You can better define your own annotations. For example:
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface FooAnnotation {
}
Then replace @Named("foo")
by @FooAnnotation
in the Bar
class and replace Names.named("Foo")
by FooAnnotation.class
in your module.
Upvotes: 5
Reputation: 49572
Unfortunatelly you cannot place annotations on local variables. This limitation comes from Java and not from Guice. According to this answer there is hope that we get this feature in future Java versions.
But please note that even if this would work it wouldn't be a good practice. The idea of dependency injection is the ability to change dependencies from outside of a class. A local variable does not fit into this because it cannot be changed from outside the class.
Upvotes: 1