2013-07-30 61 views
1

我刚开始使用Guice,所以我的理解可能完全错误。我可以在使用Guice的方法中获得实例吗?

我有一个接口Foo和implmentation 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(); 
} 

回答

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 
} 

在你吉斯模块,你必须编写

bind(Foo.class).annotatedWith(Names.named("Foo")).toInstance(foo); 
//let's say this is part of the module MyModule extends AbstractModule 

一旦您设置此,你可以在这里你用Guice的Injector -class创建对象的主方法。像这样:

Injector injector = Guice.createInjector(new MyModule()); 
Bar bar = injector.getInstance(Bar.class); 
//do something with bar 

希望这对你有帮助。如果您有更多问题,请随时问我!

提示:查看Guice的网站,观看视频,并仔细阅读wiki。 Guice是一个非常棒的工具,但在使用之前需要做一些研究。 祝你好运!


此外:在我看来,使用@Named是一种糟糕的代码风格。您可以更好地定义自己的注释。例如:

@BindingAnnotation 
@Target({ FIELD, PARAMETER, METHOD }) 
@Retention(RUNTIME) 
public @interface FooAnnotation { 
} 

然后在Bar类由@FooAnnotation取代@Named("foo")FooAnnotation.class你的模块替换Names.named("Foo")

+0

清晰且有帮助的答案。感谢您的帮助! – NSF

1

可惜的是,你不能把对局部变量的注释。这个限制来自Java而不是Guice。根据this answer,我们希望在未来的Java版本中获得此功能。

但请注意,即使这可行,这也不是一个好习惯。依赖注入的思想是能够从类外改变依赖关系。局部变量不适合这个,因为它不能从类外部改变。

+0

我没有把这个作为答案,因为Rvan的帮助更多。但仍然非常有帮助的答案。谢谢。 – NSF

0

其他答案是正确的 - 您只能注入到构造函数或字段中。将实例保留为字段是标准做法,这也允许您交换自己的实现以进行测试。

如果您需要在每次方法被调用时,产生一个新的实例,你可以使用一个Provider。对于任何给定为Foo(或@Baz FooProvider<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(...)有它的方式,它永远是相同的实例反正,但你应该需要一个新的实例的方法,这是你的最佳选择每次运行。

+0

你刚刚接受另一个答案后回答了我的问题...我稍后再检查一下。谢谢! – NSF

+0

对于有关新实例和始终同一实例的评论,您是正确的。我大部分时间做的是这样的:'bind(Foo.class).annotatedWith(...)。(FooImp.class)'。通常使用这个。涉及复杂类时,使用提供者更常用。 – RvanHeest

相关问题