如何使用Guice设置同一对象图的多个配置?

时间:2012-05-13 12:12:28

标签: java guice

您将如何构建下图中显示的对象图?

用户对象必须组合来自两个数据库后端的信息。

Multiple configurations of the same object graph

3 个答案:

答案 0 :(得分:3)

我找到了使用私有模块的解决方案。

static class Service {
    @Inject Dao daoA;

    public void doSomething() {
        daoA.doA();
    }
}

static class Dao {
    @Inject DataSource dataSource;

    public void doA() {
        dataSource.execute();
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Connection {}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface X {}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Y {}

static class DataSource {
    @Connection @Inject String connection;

    public void execute() {
        System.out.println("execute on: " + connection);
    }
}

static class XServiceModule extends PrivateModule {
    @Override
    protected void configure() {
        bind(Service.class).annotatedWith(X.class).to(Service.class);
        expose(Service.class).annotatedWith(X.class);

        bindConstant().annotatedWith(Connection.class).to("http://server1");
    }
}

static class YServiceModule extends PrivateModule {
    @Override
    protected void configure() {
        bind(Service.class).annotatedWith(Y.class).to(Service.class);
        expose(Service.class).annotatedWith(Y.class);

        bindConstant().annotatedWith(Connection.class).to("http://server2");
    }
}

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

    Service serviceX = injector.getInstance(Key.get(Service.class, X.class));  
    serviceX.doSomething(); 

    Service serviceY = injector.getInstance(Key.get(Service.class, Y.class));
    serviceY.doSomething(); 
}
  • 可以通过X和Y注释来标识Service类的不同实例。
  • 通过隐藏私有模块中的所有其他依赖项,Dao和DataSource之间没有冲突
  • 在两个私有模块中,可以用两种不同的方式绑定Constant
  • 通过公开曝光服务。

答案 1 :(得分:0)

我要说你应该使用assisted injection扩展程序来Guice生成一个工厂,将Service转换为DataSource,然后将该工厂应用于两个不同的{{ 1}} S上。

答案 2 :(得分:0)

您可以使用BindingAnnotations或简单地使用通用的@Named Annotation。我发现它们最简单地与@ Provide-Methods一起使用:

@Provides
@Named("User1")
public SomeUser getUser(Service1 service) {
   return service.getUser();
}
@Provides
@Named("User2")
public SomeUser getUser(Service2 service) {
   return service.getUser();
}

然后:

@Inject
@Named("User1")
private SomeUser someuser;
...