gpt4 book ai didi

java - 如何使用 Guice 注入(inject)器创建对象?

转载 作者:行者123 更新时间:2023-11-29 04:23:15 24 4
gpt4 key购买 nike

我的代码中有:

private static class BaseScriptInfoParser extends NodeParser<Asset.ScriptInfo> {

private Asset.ScriptKindEnum scriptKind;

private final NodeParser<Asset.TransformerKindEnum> transformerKindNodeParser;
private final NodeParser<Asset.ValidatorKindEnum> validatorKindNodeParser;

@Inject
BaseScriptInfoParser(
// First two arguments are injectors
@Named("transformerKind") NodeParser<Asset.TransformerKindEnum> transformerKindNodeParser,
@Named("validatorKind") NodeParser<Asset.ValidatorKindEnum> validatorKindNodeParser,
Asset.ScriptKindEnum scriptKind)
{
this.scriptKind = scriptKind;
this.transformerKindNodeParser = transformerKindNodeParser;
this.validatorKindNodeParser = validatorKindNodeParser;
}

// ...

}

现在我想创建一个没有类似代码的 BaseScriptInfoParser 实例(因为据我所知,它应该只在 Main 函数中)

Injector injector = Guice.createInjector(new BoilerModule());
// ...

我能否只调用一个构造函数来创建一个带有一个参数(Asset.ScriptKindEnum 类型)的 BaseScriptInfoParser 类的对象,并自动注入(inject)前两个参数?

或者如何使用注入(inject)器创建对象?

如果构造函数 BaseScriptInfoParser 没有第三个参数,它将如何工作?

最佳答案

避免额外调用 createInjector 是正确的,并避免传递您创建的 Injector。对于最佳 Guice 实践,您应该准确指定任何给定组件创建或依赖的对象,而 Injector 恰恰相反:它可以创建任何东西。

相反,一般来说,您应该从图中注入(inject)您需要的对象。如果你认为你以后可能只需要一个对象,或者你可能需要一个对象的多个实例,你可以注入(inject)一个 Provider<T>相反(其中 T 是图中可用的任何对象),然后您可以稍后请求该实例,就好像您调用了 getInstance (但不创建新对象或使图形的其余部分可用)。这也应该使测试更容易,因为 simulating a Provider in tests is very easy ,但是模拟 Injector 很困难,使用真实的 Injector 既昂贵又复杂。

如果 BaseScriptInfoParser 没有这个手动的第三个参数,你可以直接注入(inject) Provider<BaseScriptInfoParser> : Guice 会自动处理这个只要 BaseScriptInfoParser有一个公共(public)的无参数构造函数,一个 @Inject带注释的构造函数,或 bind(BaseScriptInfoParser.class)绑定(bind)或 @Provides BaseScriptInfoParser模块中的方法。


现在,关于混合注入(inject)构造函数参数和非注入(inject)参数:

并非图表中的每个对象都需要是可注入(inject)的:要使用 Miško Hevery 的术语,来自他的 "To new or not to new " article ,您的应用程序可能由来自图表的可注入(inject)和一些新事物组成,例如“值对象”和“数据对象”,它们具有很多状态且没有依赖性.

但是,对于某些对象,构造函数提供的不可变状态同时从图中访问可注入(inject)对象是有意义的,而无需将两者分离到单独的对象中(这也是一种选择)。实际上,您想要的是您的 DI 框架可以提供的对象,它实现了这个接口(interface):

interface BaseScriptInfoParserFactory {
/**
* Calls the BaseScriptInfoParser constructor, with other constructor params
* injected from the graph.
*/
BaseScriptInfoParser create(Asset.ScriptKindEnum scriptKind);
}

因为这是一个定义非常明确的类,所以 Google 提供了几个不同的选项来自动生成类:您可以使用 Guice 的反射 Assisted InjectionAutoFactory来自代码生成 Google Auto包裹。后者更快一些,因为它生成普通代码而不是运行时反射代码,但前者与 Guice 的集成稍微好一些:

  1. 确保 Guice 辅助注入(inject) JAR 位于类路径中。它是分开的。

  2. 标记您的构造函数以说明哪些参数应来自 Guice:

    @Inject BaseScriptInfoParser(
    @Named("transformerKind") NodeParser<...> transformerKindNodeParser,
    @Named("validatorKind") NodeParser<...> validatorKindNodeParser,
    @Assisted Asset.ScriptKindEnum scriptKind)
  3. 编写一个可以注入(inject)的工厂接口(interface),我喜欢将其作为嵌套接口(interface)来做:

    public class BaseScriptInfoParser {
    public interface Factory {
    // Any interface and method name works. These are the most common.
    BaseScriptInfoParser create(Asset.ScriptKindEnum scriptKind);
    }
    // ... rest of the class, including the above constructor
    }
  4. 告诉 Guice 编写一个实现并绑定(bind)到它:

    public class YourModule extends AbstractModule {
    @Override public void configure() {
    install(new FactoryModuleBuilder()
    .build(BaseScriptInfoParser.Factory.class));
    }
    }
  5. 注入(inject)你的 BaseScriptInfoParser.Factory并调用create(someScriptKind)每当您需要新对象时。

关于java - 如何使用 Guice 注入(inject)器创建对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47874305/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com