Guice:请求实例,而不是类型

时间:2012-04-13 13:15:27

标签: java spring dependency-injection guice

让我们发表声明“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实例,该实例本身配置了M1 Mineral实例。

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

使用Guice,您只能询问所需的类型Rock.class),而不是实例

您如何使用Guice请求不同的“有线bean”?使用不同的AbstractModule结核?或者这是Guice的限制吗?

2 个答案:

答案 0 :(得分:1)

我怀疑你想要binding annotations。 Guice不会通过类型绑定 - 它通过绑定 - 但如果你不做任何其他操作,那么键只会包含类型。绑定注释允许您创建更丰富的密钥。

链接文档比我更好地解释了它,但结果是有多种方法可以指定你想要的东西,包括:

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

@Inject
public Foo(@HardRockCafe Rock rock)

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

答案 1 :(得分: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

这让我们分道扬..但是如果你想在运行时使用两种独特的Rock and Mineral配对,那么这就是Guice所说的“机器人腿”问题,你可以使用私有模块解决它即可。查看示例here