Guice 在类中注入字段不是由 Guice 创建的

发布于 2024-09-13 04:20:37 字数 508 浏览 7 评论 0原文

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

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 应该如何工作的吗?

I have a class like so, that I create myself somewhere in my code:

class StarryEyes {
   @Inject MyValidator validator;

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

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

I want Guice to inject an instance of validator, which has a @Singleton annotation.
I have a module that's loaded at startup and it contains the line:

bind(MyValidator.class);

However, it doesn't seem to work as "validator" is always null. I've tried a number of variations like:

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

or other things like that. Is this not how Guice is supposed to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红尘作伴 2024-09-20 04:20:37

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

您真正想要的可能是辅助注入。使用辅助注入,您可以为类声明构造函数,如下所示:

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

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

然后,您创建一个如下所示的接口:

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

通过辅助注入,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));

Typically Guice needs to create objects to inject them. If you just call new StarryEyes(name), Guice isn't ever going to see that object so it won't be able to inject it. One thing you can do is to call injector.injectMembers(obj) on the object after you've created it. I wouldn't recommend that, though, as you should avoid referencing the injector in your code.

What you really probably want here is Assisted Inject. With Assisted Inject, you'd declare the constructor for your class something like this:

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

What that means is that validator is a parameter that Guice should inject, while name must be "assisted" (that is, provided at the time the instance is created).

You then create an interface like this:

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

With Assisted Inject, Guice can then implement that factory for you. You bind it like this:

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

You then inject a StarryEyesFactory anywhere you want to create an instance of it. Where you would have called new StarryEyes(name) previously, you now call starryEyesFactory.create(name) instead. When you call create(name) on the factory, it will take the name and pass it to the constructor and provide the bound validator itself.

Starting in Guice 3, you do this using a FactoryModuleBuilder:

install(new FactoryModuleBuilder().build(StarryEyesFactory.class));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文