使用Guice使用提供程序对服务的多个实现

时间:2014-02-19 15:53:55

标签: java guice

我需要建议如何使用Google-guice为服务的多个实现进行编码。以下是示例

TestService testService =new TestServiceImplOne();
TestService testService =new TestServiceImplTwo();

由于Guice不允许将类型绑定到多个实现,因为以下代码会导致错误

binderObject.bind(SomeType.class).to(ImplemenationOne.class);
binderObject.bind(SomeType.class).to(ImplemenationTwo.class);

我们可以通过命名注释来解决这个问题,如下所示

binder.bind(Player.class).annotatedWith(Names.named("Good")).to(GoodPlayer.class);
binder.bind(Player.class).annotatedWith(Names.named("Bad")).to(BadPlayer.class);

@Named("Good") Player goodPlayer = (Player)injector.getInstance(Player.class);
@Named("Bad") Player badPlayer = (Player)injector.getInstance(Player.class);

但我工作的应用程序是这样的。我们绑定init()方法中的所有模块并创建注入器模块:

//separate method to bind
protected void configure() {
  bind(new TypeLiteral<List<Service>>() {}).toInstance(serviceSets);
}

//separate method to inject
Injector i = Guice.createInjector(modules);

但是通过上面的过程,我可以将一个实现类绑定到接口(服务类)

能否请您与供应商联系。我想在下面做这样的事情

class  TestServiceProvider extends Provider{
// some code where it returns the  instance of impl class needed. In my case TestServiceImplOne and TestServiceImplTwo and provider returns the corresponding instance of service class
}

并将服务类与提供程序类绑定。像这样的东西

bind(TestService.class).toProvider(TestServiceProvider.class);

如果有人建议使用提供程序或其他方式我可以在客户端注入我想要的任何实现,我将不胜感激。

注意:我正在使用webservices,我不确定在向服务类调用webservice时如何注入不同的实现。


First of all thanks very much for responding . Coming straight to the point

Iam working on webservices . Heres's the Flow

// GET URI     获取http://www.google.com:8182/indi/provide/organizations/ {ou}

OrganizationsResource -------->OrganizationService------>OrganizationServiceImpl

Iam binding OrganizationService with OrganizationServiceImpl and injecting the OrganizationService in OrganizationsResource

@Inject
    public void setOrganizationService(OrganizationService orgService) {
        this.orgService= orgService;
    }


Its fine till here but i have two implementations for OrganizationService ------>OrgDeatilsServiceImpl which does some other job

Now i want to bind both OrganizationServiceImpl and OrgDeatilsServiceImpl to OrganizationService

Confusions:

1) What procedure i have to use in Guice to bind two implementaions?
2) How exactly i can code in OrganizationsResource  to dynamically decide which implementation to call.


I would appreciate if you give a sample example for the above requirement. 

1 个答案:

答案 0 :(得分:4)

正如弗拉基米尔所说,你可以使用与提供者的绑定注释......

// in YourModule.configure():
bind(TestService.class)
    .annotatedWith(Names.named("foo")
    .toProvider(TestServiceProvider.class);

...和使用TypeLiterals的泛型类型......

bind(new TypeLiteral<List<Service>>() {})
    .annotatedWith(Names.named("bar")
    .toInstance(serviceSets);

...只要您使用getInstance(Key<T>) ...

请求带注释的实例
List<Service> servicesOne = injector.getInstance(
    new Key<List<Service>>(Names.named("bar")) {});
// or
List<Service> servicesTwo = injector.getInstance(
    Key.get(new TypeLiteral<List<Service>>() {}, Names.named("bar"));

...或者,最好将它们保留为字段并让Guice进行注入,因为Guice无法注入局部变量。请记住,Guice只能注入它创建的类,或者您专门请求的类。

class MyInjectorCreator {
  @Inject @Named("foo") Provider<TestService> fooServiceProvider;
  @Inject @Named("bar") List<Service> barServices;
  // Guice will also wrap/unwrap Providers automatically.
  @Inject @Named("foo") TestService fooService;
  @Inject @Named("bar") Provider<List<Service>> barServicesProvider;

  public void createInjector() {
    Injector injector = Guice.createInjector(getListOfModules());
    injector.injectMembers(this);
  }
}

现在,当你在标题中表达时,它回答了这个问题。也就是说,听起来你真的想在运行时选择实现,这是一个稍微不同但易于解决的问题:

class TestServiceProvider extends Provider<TestService> {
  // Injection is allowed here!
  @Inject ApplicationSettings settings;
  @Inject Provider<TestServiceImplOne> oneProvider;
  @Inject Provider<TestServiceImplTwo> twoProvider;

  @Override public TestService get() {
    if (settings.isInTestMode()) {
      return new TestTestServiceImplImpl(); // without injection!
    } else if (settings.useNewService()) {
      return twoProvider.get(); // with injection!
    } else {
      return oneProvider.get(); // also with injection!
    }
  }
}

但是我应该警告你,如果你知道在注射器创建时使用哪种服务,你可能应该正确绑定它,然后为了代码清洁和易于阅读:

// in YourModule.configure():
if (settings.isInTestMode()) {
  bind(TestService.class).toInstance(new TestTestServiceImplImpl());
} else if (settings.useNewService()) {
  bind(TestService.class).to(TestServiceImplTwo.class);
} else {
  bind(TestService.class).to(TestServiceImplOne.class);
}