【问题标题】:Guice: requesting instances, not typesGuice:请求实例,而不是类型
【发布时间】:2012-04-13 13:15:26
【问题描述】:

让我们声明“All Rocks have Minerals.”:

public class Mineral
{
    // Nevermind why a Mineral would have a GUID.
    // This is just to show that each Mineral instance
    // is universally-unique.
    String guid;

    @Inject
    public Mineral(String id)
    {
        guid = id;
    }
}

public class Rock
{
    private Mineral mineral;

    @Inject
    public Rock(Mineral min)
    {
        mineral = min;
    }
}

如果我们想要 2 个 Rock 实例,每个实例都配置有不同的 Mineral 实例(每个实例都有自己的 GUID):

public class RockModule extends AbstractModule
{
    public void configure(Binder binder)
    {
        // Make two Minerals with different GUIDs.
        Mineral M1 = new Mineral(UUID.getRandomId().toString());
        Mineral M2 = new Mineral(UUID.getRandomId().toString());

        // Configure two Rocks with these unique Minerals
        Rock R1 = new Rock(M1);
        Rock R2 = new Rock(M2);

        // Define bindings
        bind(Rock.class).toInstance(R1);

        // No way for Guice to expose R2 to the outside world!
    }
}

所以现在,当我们向 Guice 请求 Rock 时,它总是会给我们 R1 实例,它本身配置有 MineralM1 实例。

在 Spring DI 中,您可以将两个 bean 定义为相同的类型,但只需给它们不同的 bean ID。然后,您使用它们的 ID 将 bean“连接”在一起。所以我可以将R1M1 连接在一起,将R1M2 连接在一起,等等。然后,我可以根据需要向Spring 询问R1R2

使用 Guice,您只能询问您想要的 type (Rock.class),而不是 instance

您如何使用 Guice 请求不同的“有线豆”?通过使用不同的AbstractModule 凝结物?或者这是 Guice 的限制?

【问题讨论】:

    标签: java spring dependency-injection guice


    【解决方案1】:

    通常这会违反 Guice 的建议。您通常不会 new 在模块内部创建一个类来创建实例,因为它首先违背了使用 DI 容器的目的。 (为什么还要用@Inject注释你的类?)

    相反,你会让 Guice 为你做这件事:

    class RockModule extends AbstractModule {
      public void configure() {}
    
      @Provides
      @Named("UUID")
      public String getUuid() {
        return UUID.getRandomId().toString();
      }
    }
    

    现在每个Mineral 自动获得一个唯一的UUID,每个Rock 获得一个唯一的Mineral

    这让我们分道扬镳,但如果您想要在运行时使用岩石和矿物的两个独特配对,那么这就是 Guice 所说的“机器人腿”问题,您可以使用 私有模块来解决它。查看示例here

    【讨论】:

      【解决方案2】:

      我怀疑你想要binding annotations。 Guice 不按 type 绑定 - 它按 key 绑定 - 但如果您不执行任何其他操作,则密钥将仅由类型组成。绑定注释允许您创建更丰富的键。

      链接的文档解释得比我好,但结果是有多种方法可以指定您想要的内容,包括:

      @Inject
      public Foo(@Named("X") Rock rock)
      

      @Inject
      public Foo(@HardRockCafe Rock rock)
      

      在后一种情况下,@HardRockCafe 是自定义绑定注释。

      【讨论】:

      • @herpylderp:嗯,这取决于你所说的“完全”是什么意思——但基本上,是的。
      猜你喜欢
      • 2011-08-22
      • 2020-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      相关资源
      最近更新 更多