我刚开始使用Guice,所以我的理解可能完全错误。
我有一个界面Foo
和一个实施FooImp
我在我的模块中使用了以下代码来注入它:
bind(Foo.class).annotatedWith("Foo").toInstance(foo); // foo is an instance of FooImp
然后我现在想在我的代码中,名称注释为“Foo”的Foo
实例将被foo
替换?
@Named("Foo")
Foo fooInst; // fooInst will be foo at runtime?
如果我是对的,我怎么能做到这一点:
public Foo doSomething() { // for some reason there must be no arguments
@Named("Foo")
Foo fooInst; // injecting here seems not allowed...?
fooInst.do();
}
答案 0 :(得分:3)
你所假设的并不完全正确:Guice用于依赖注入,这意味着你可以将一些接口/类注入到另一个类的构造函数中。
假设您有一个界面Foo
,它的实现FooImpl
。然后你还有一个类Bar
,它取决于Foo
的实现。
public class Bar {
private Foo foo;
@Inject
public Bar(@Named("foo") Foo foo) {
this.foo = foo;
}
//some other methods
}
在你的Guice模块中你必须写
bind(Foo.class).annotatedWith(Names.named("Foo")).toInstance(foo);
//let's say this is part of the module MyModule extends AbstractModule
设置完成后,您可以使用Guice的Injector
- 类创建一个主方法来创建对象。像这样:
Injector injector = Guice.createInjector(new MyModule());
Bar bar = injector.getInstance(Bar.class);
//do something with bar
希望这能帮到你。如果您有更多问题,请随时问我!
提示:查看Guice的网站,观看视频并仔细阅读维基。 Guice是一个非常棒的工具,但在使用之前你需要做一些研究。 祝你好运!
另外:在我看来,使用@Named
是一种糟糕的代码风格。您可以更好地定义自己的注释。例如:
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface FooAnnotation {
}
然后将@Named("foo")
替换为@FooAnnotation
类中的Bar
,并将Names.named("Foo")
替换为模块中的FooAnnotation.class
。
答案 1 :(得分:1)
不幸的是,您无法在局部变量上添加注释。这种限制来自Java,而不是来自Guice。根据{{3}},我们希望在未来的Java版本中获得此功能。
但请注意,即使这样可行,也不是一个好习惯。依赖注入的想法是能够从类外部更改依赖关系。局部变量不适合这个,因为它不能从类外部更改。
答案 2 :(得分:0)
其他答案是正确的 - 您只能注入构造函数或字段。将实例保留为字段是标准做法,这也允许您交换自己的实现进行测试。
如果每次调用方法时都需要生成新实例,则可以使用Provider
。对于Foo
(或@Baz Foo
)的任何给定绑定,Provider<Foo>
(或@Baz Provider<Foo>
)为bound automatically,无需任何额外代码。
public class Bar {
private Provider<Foo> fooProvider;
@Inject
public Bar(@Named("foo") Provider<Foo> fooProvider) {
this.fooProvider = fooProvider;
}
public doSomething() {
Foo foo = fooProvider.get();
}
}
当然,你使用bind(...).toInstance(...)
的方式,它总是相同的实例,但如果你需要为每次运行方法都需要一个新的实例,这是你最好的选择。