java - Guice 和 "scoped"单例

标签 java dependency-injection guice

我正在尝试学习 Guice,但以下场景似乎很难。假设我有 A、B 和 C 类。我应该能够执行以下操作(请注意,此示例对实际情况有所简化):

  1. A是全局单例
  2. A 依赖于 ProviderB(即工厂)
  3. B 依赖于 A 和 ProviderC(即工厂)
  4. C 依赖于 A 和 B

当B创建C时,C的依赖B必须是同一个实例,即从C的角度来看,B是单例。

我试过创建子注入(inject)器:

private static class MainModule extends AbstractModule{

    @Override
    protected void configure() {
        bind(A.class).in(Singleton.class);
    }

    @Provides
    B createB(Injector injector){
        return injector.createChildInjector(new SubModule()).getInstance(B.class);
    }
}

private static class SubModule extends AbstractModule{

    @Override
    protected void configure() {
        bind(B.class).in(Singleton.class);
        bind(C.class);
    }
}

public static void main(String[] args) {
    Injector injector = Guice.createInjector(new MainModule());

    A a = injector.getInstance(A.class);

    B b1 = a.getB();
    B b2 = a.getB();

    // all following C's are different instances
    C b1c1 = b1.getC(); //this has b1 and a
    C b1c2 = b1.getC(); //this has b1 and a

    C b2c1 = b2.getC(); //this has b2 and a
    C b2c2 = b2.getC(); //this has b2 and a

但是随后 Guice 给出了 B 已经绑定(bind)的错误(MainModule 中的 Provides 方法)。因此我需要重写 MainModule 的 B 绑定(bind),但这似乎无法使用子注入(inject)器。

这个问题可以通过使用多个注入(inject)器来解决,例如为 createB 方法创建一个新的并将 A 作为参数注入(inject),但似乎使用多个注入(inject)器不是最佳实践。

编辑:向 C 实例添加注释以阐明它们应该拥有哪个 B 实例

最佳答案

我会将其作为答案发布,它更像是解决方法而不是完整的解决方案,但对于我的应用程序来说可能已经足够好了:

private static class MainModule extends AbstractModule{

    @Override
    protected void configure() {
        bind(A.class).in(Singleton.class);
        bind(SubModule.class).in(Singleton.class);
    }

    @Provides
    B createB(Injector injector){
        SubModule m = injector.getInstance(SubModule.class);
        return Guice.createInjector(m).getInstance(B.class);
    }
}

private static class SubModule extends AbstractModule{

    private final A a;

    @Inject
    public SubModule(A a) {
        this.a = a;
    }

    @Override
    protected void configure() {
        bind(A.class).toInstance(a);
        bind(B.class).in(Singleton.class);
        bind(C.class);
    }
}

首先,我认为大多数绑定(bind)都将在 MainModule 中,但我想如果它们仅在 B 的上下文中使用(并像我对 A 所做的那样路由其他人),无论如何都可以将它们移动到 SubModule。这主要类似于链接问题的答案: Dependency injection: Scoping by region (Guice, Spring, Whatever)但是我创建了新的顶级注入(inject)器,因为我似乎无法在两个模块中绑定(bind) B,否则我可能会在这里遗漏一些东西..

(第一次这样做,不确定这是否是发布解决方法作为自己的答案的正确方法)

关于java - Guice 和 "scoped"单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28827911/

相关文章:

java - JPA+ hibernate : CriteriaQuery not loading eager ManyToOne relation

java - 播放文件时出错 : NullPointerException in Android

java - 使用 Java 根据扩展名检索目录的第一个文件

java - Dagger 组件有冲突的作用域

guice - 如何在 Quarkus 中引导 Guice Injector?

java - 用Java编写文件时如何避免额外的头字节?

Angularjs 4 - 注入(inject)服务而不在构造函数上传递参数

java - 如果您的模块本身将参数作为构造函数传入,如何注入(inject)依赖项?

dependency-injection - 如何注入(inject)注入(inject)器?

java - Guice 提供者方法是否尊重范围?