Guice Inject Field中的字段不是由Guice创建的

时间:2010-08-04 11:03:04

标签: java null guice code-injection

我有一个这样的课程,我在我的代码中创建了自己的地方:

class StarryEyes {
   @Inject MyValidator validator;

   public StarryEyes(String name) {
      //..
   }

   public doSomething() {
      // validator is NULL
   }
}

我希望Guice注入一个验证器实例,它有一个@Singleton注释。 我有一个在启动时加载的模块,它包含以下行:

bind(MyValidator.class);

然而,它似乎不起作用,因为“验证器”始终为空。我尝试了很多变体,如:

bind(MyValidator.class)toInstance(new MyValidator());

或类似的其他事情。这不是Guice应该如何运作的吗?

1 个答案:

答案 0 :(得分:33)

通常Guice需要创建注入它们的对象。如果你只是打电话给new StarryEyes(name),Guice永远不会看到那个对象,所以它无法注入它。您可以做的一件事是在创建对象后调用injector.injectMembers(obj)。但是,我不建议您这样做,因为您应该避免在代码中引用注入器。

你真正想要的是Assisted Inject。使用Assisted Inject,您可以为您的类声明构造函数:

@Inject public StarryEyes(MyValidator validator, @Assisted String name)

这意味着validator是Guice应该注入的参数,而name必须是“辅助”(即,在创建实例时提供)。

然后创建一个这样的界面:

public interface StarryEyesFactory {
  StarryEyes create(String name);
}

通过Assisted Inject,Guice可以为您实现该工厂。你像这样绑定它:

bind(StarryEyesFactory.class).toProvider(
    FactoryProvider.newFactory(StarryEyesFactory.class, StarryEyes.class));

然后,您可以在任何想要创建其实例的地方注入StarryEyesFactory。您之前呼叫new StarryEyes(name)的地方,现在请拨打starryEyesFactory.create(name)。当您在工厂中调用create(name)时,它将获取名称并将其传递给构造函数并提供绑定的验证器本身。

从Guice 3开始,您使用FactoryModuleBuilder执行此操作:

install(new FactoryModuleBuilder().build(StarryEyesFactory.class));