当前位置: 首页 > 知识库问答 >
问题:

运行时注射:如何用Guice获得最幼稚的注射器?

别浩漫
2023-03-14

基本上我的问题归结为如何让这个测试通过:

private static class DefaultModule extends AbstractModule {
    @Override protected void configure() {
    }
}
private static class ParentModule extends DefaultModule{}
private static class ChildModule extends DefaultModule {}

private static class DependsOnInjector{
    @Inject
    public Injector depdendency;
}

@Test
public void when_instancing_a_class_that_depends_on_an_injector_it_should_yield_the_most_childish(){ 
    //childish :p
    Injector parent = Guice.createInjector(new ParentModule());
    Injector child = parent.createChildInjector(new ChildModule());

    DependsOnInjector objectWithInjector = child.getInstance(DependsOnInjector.class);

    assertThat(objectWithInjector.depdendency).isSameAs(child);
}

但也许我错过了重点:堆栈溢出会让你相信做我正在做的事情是一种罪过(介绍引用喷油器的工厂,当你要求他们制造产品时,他们只是转发给你),而我正在做的是接近服务定位器,这是一个糟糕的举动。但我看不出解决这个问题的方法。

我有一个名为“可视化”的接口,它有7个实现者。运行时,根据您的数据集,我们选择一组可视化工具来创建和呈现。对于有注入器字段的工厂,我只需添加一个方法

public <TVis extends Visualization> TVis makeVisualization(Class<TVis> desiredVisualizationType){
    return injector.getInstance(desiredVisualizationType);
}

我认为让工厂保留一个IOC容器作为一个字段的唯一选择是让guice的7个辅助注入工厂,每个实现一个,由一个开关选择。这太恶心了。

这是几个例子之一。我真的很想找到一个很好的方法来获得最本地的注射器。

编辑,澄清:

有许多地方可以方便地将注射器封装在某种解码器中。可视化工具是一个实例,但还有其他几个实例。感谢您提供关于地图绑定的提示。我现在遇到的问题是,我们的可视化工具(无论好坏……我怀疑更糟)希望在每次需要时都能被实例化。所以,即使有了映射绑定,我仍然需要向可视化工具解码逻辑类中注入注入器,不是吗?

关于我有多少个模块:我目前有4个guice模块:一个共享的,它注册了我的许多大的(真正的)单例服务,然后一个用于我们的“托管”用户界面,然后一个用于我们的“问题设置”用户界面,另一个用于我们的“外部工具”用户界面(事实上,我们的测试环境还有一个)。后两个用户界面模块的数量是任意的,每个模块都有几个创建得很晚的对象。这意味着不使用子模块,我相信我会留下几个映射绑定器,每个绑定器都在运行时添加到它们中(然后,大概是为了内存泄漏,在处置时添加了某种删除逻辑)。在我看来,让我的(组合!)guice模块树(读:不是继承树!)

感谢您的任何帮助,并感谢现有的建议。

共有3个答案

壤驷向明
2023-03-14

如果您只想在运行时获得正确的实例,为什么不能在您的模块中添加一个< code>@Provides方法来实例化< code>Visualizations?

江渊
2023-03-14

我有一个名为“可视化”的界面,它有7个实现者。运行时,根据您的数据集,我们选择一组这些可视化工具来创建和渲染。

如果您的可视化工具集已修复,请考虑使用纯绑定注释。这是用于区分同一接口的多个实现的最简单的方法。为此,您不需要多个喷油器。

如果您的可视化工具集不是固定的(例如,这些可视化工具是插件),那么您的任务可以使用 MapBinder 巧妙地解决。有了它,您也不需要多个注入器,您可以在单个注入器中定义所有可视化

public class VisualizationsModule extends AbstractModule {
    @Override
    protected void configure() {
        MapBinder<Class<Visualization>, Visualization> binder =
            MapBinder.newMapBinder(binder(), new TypeLiteral<Class<Visualization>>() {},
                                   TypeLiteral.get(Visualization.class));
        binder.addBinding(Visualization1.class).to(Visualization1.class);
        binder.addBinding(Visualization2.class).to(Visualization2.class);
        // etc
    }
}

然后您可以注入一个< code >映射

@Inject
public SomeClass(Map<Class<Visualization>, Visualization> visualizers) {
    ...
}

您可以选择任意键,而不仅仅是<code>Class

锺离俊雄
2023-03-14

要回答你的第一个问题,可以通过添加一个显式的< code > bind(dependsoninjector . class)来获得想要的注入器;到< code>ChildModule。否则,“为子注入器创建的实时绑定将尽可能在祖先注入器中创建。”

 类似资料:
  • 我有一个Maven模块,我在其中定义了一些跨其他几个Maven模块共享的UTIL。在本模块中,我想创建一些单例: 然后我将我的界面绑定到: 假设我想使用另一个Maven模块(比如web服务)中的这个单例,我该如何实现呢?我找到的唯一方法是在util Maven模块中创建一个类,如: 或者,我可以在Guice教程中看到的静态main方法中创建注入器,并将实例保存在某个地方。 然后从我的Web服务中执

  • 问题内容: 我让Google Guice负责连接对象。但是,如何测试绑定是否运作良好? 例如,假设我们有一个具有依赖性的类。如何测试B是否正确注入? 注意,这里没有方法,我想断言不是。 问题答案: 对于任何复杂的Guice项目,您都应该添加测试以确保可以使用这些模块来创建您的类。在您的示例中,如果B是Guice无法弄清楚如何创建的类型,则Guice将无法创建A。如果不需要A来启动服务器,但是当服务

  • 我使用< code>Cucumber和< code>Guice作为DI。我遇到了以下问题:我有一个步骤,即 我让这个类作为测试运行它 有一个 由我的使用,我定义了cucumber.properties,我定义了还有一个包含方案的功能文件。现在一切都在工作。 不,我想使用其他MyService实现运行MyStep步骤(当然我不会重复MyStep的代码)我定义了一个具有新场景和新测试类的新功能文件 现

  • 我对使用Guice有疑问。我有一个名为< code>Main的类,它是使用Guice和一个方法注入的构造函数,每次调用该方法都会创建一个类< code>AppThread的o thread对象。< code>AppThread是< code>Main中的私有类。问题是,在线程的执行过程中,我想创建一个class 的对象。此对象是使用Guice注入的构造函数。我不知道注入< code>ClassX的

  • 问题内容: 假设我有一个模块: 我想测试模块并检查它是否在没有类和字段但直接从注入器获取值的带注释的字段中注入正确的值: 问题答案:

  • 我已经使用google-guice和辅助注射机制有一段时间了。因为我在scala,刚刚发现scala-guice,我也对使用它感兴趣。但是我对如何使用辅助注射感到困惑。没有使用辅助注射的例子。 因此,我的问题是:是否可以使用scala guice辅助注射,如果可以,请提供一个简单的例子? 此外,对于google-guice,我使用以下库:javax.inject.jar、guice-3.0.jar