如何实施机器人腿"使用Google Guice的案例?

时间:2016-03-03 22:12:38

标签: java dependency-injection guice

我正在学习Google Guice。你知道如何实现"机器人腿"问题?让我用一个例子解释一下。

我们说我有一个名为Service的课程:

@Singleton
public class Service {
    @Inject
    Source source;

}

接口Source有两个实现:

public class SourceDatabase implements Source {

}

public class SourceFileSystem implements Source {

}

我的模块实现如下:

public class MyModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Service.class).asEagerSingleton();
    }
}

嗯,我想知道这是否可行:

public class MainClass {    

    @Inject @SomeAnnotation("database")
    Service serviceWithADatabaseSource;

    @Inject @SomeAnnotation("file-system")
    Service serviceWithAFileSystemSource;

}

是否存在允许我这样做的注释或绑定,让我注释像serviceWithADatabaseSource这样的成员,这有助于Guice知道内部成员source应注入{{1实施?

编辑:感谢Daniel Martin,在他的评论中给我们这个问题的名称。

1 个答案:

答案 0 :(得分:3)

作为documented in the Guice Wiki,您需要安装两个PrivateModule,每个enter image description here都会为您公开一个带有正确注释的服务。

public class MyModule extends AbstractModule {
  @Override
  protected void configure() {
    install(new PrivateModule() {
      @Override public void configure() {
        // Bind Source to SourceDatabase.
        bind(Source.class).to(SourceDatabase.class);
        // Bind @Named("database") Service to Service.
        bind(Service.class).annotatedWith(Names.named("database"))
            .to(Service.class);
        // Now expose @Named("database") Service without exposing
        // either of the other two conflicting bindings.
        expose(Service.class).annotatedWith(Names.named("database"));
      }
    });
    install(new PrivateModule() {
      @Override public void configure() {
        // Same as above.
        bind(Source.class).to(SourceFileSystem.class);
        bind(Service.class).annotatedWith(Names.named("file-system"))
            .to(Service.class);
        expose(Service.class).annotatedWith(Names.named("file-system"));
      }
    });
  }
}

如果模块不是PrivateModule实例,那些与Source和Service的绑定将相互冲突。但是,相反,每个绑定都会继承Injector中的所有公共绑定,但只会将@Named(...) Service暴露给外部世界。这样,相同的Service实现可以注入相同的非注释Source,但让它返回不同的完全注入类型。

另请注意,您将无法在PrivateModule之外请求SourceService(没有注释),因为您尚未在任何非私有模块中建立绑定。这应该是预期的:PrivateModule绑定不应该与任何公共绑定冲突,并且没有通过PrivateModule的暴露绑定之一进入,Guice将不知道返回哪个SourceService。 p>

最后,假设Module实例可以采用构造函数参数,最好将两个匿名内部PrivateModule提取到命名等效项中:

public class MyModule extends AbstractModule {
  @Override
  protected void configure() {
    install(new SourcePrivateModule(SourceDatabase.class, "database"));
    install(new SourcePrivateModule(SourceFileSystem.class, "file-system"));
  }
}