当前位置: 首页 > 知识库问答 >
问题:

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

陶瀚玥
2023-03-14

我需要一个关于如何使用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);

如果有人建议一个使用提供者的好例子,或者我可以在客户端中注入任何我想要的实现的其他方式,我会很感激。

注意:我正在使用 Web 服务,我不确定当 Web 服务被调用到服务类时如何注入不同的实现。

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

Iam working on webservices . Heres's the Flow

//得到http://www.google.com:8182/indi/provide/organizations/{ou}得到URI

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个答案

鲜于煜祺
2023-03-14

正如 Vladimir 所指出的,您可以将绑定注释与提供程序一起使用......

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

…和使用Type的泛型类型…

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

…只要您使用<code>getInstance(键

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);
}
 类似资料:
  • 我有一个Guice,它的构造函数接受注入的参数: 现在,我希望能够注入参数取决于我运行此参数的环境。在测试中,我想注入一个 MyConfiguration 对象,而在生产中,我想注入另一个对象。 我有两个MyConfiguration提供程序。MyConfigurationProvider读取外部配置文件并从那里获取配置。MyConfigurationTestProvider只是对所有设置进行硬编

  • 问题内容: 我有一个包含20个左右注释实现的接口。如果知道在编译时需要的内容,则可以注入正确的内容,但是现在我需要根据运行时参数动态注入内容。 据我了解的文档,我将不得不使用20次左右的注射,然后再使用所需的注射,这对我来说似乎太过分了。有没有一种方法可以绑定特定的实现,然后仅将其注入我的类中? 问题答案: 注入一个[MapBinder](https://google.github.io/guic

  • 这是一个奇怪的用例,我需要一些帮助来弄清楚如何相互结合使用辅助/提供者/FactoryModuleBuilders。忽略的缺失。这只是一个例子。 属于我无法更改的库的一组特征具有以下模式。它使用蛋糕图案。 由于这些特征不能被直接注入,我创建了一个允许它们被注入的包装器 在我的代码中,我有一个依赖于服务的控制器,而服务又依赖于库。根据控制器的需要,服务应能够使用“BB”或“CC”。组件如下所示 我将

  • 我的应用程序中有两个绑定类型的命名实例: 我有一个类,希望每个类使用一个实例。由于技术原因,此类不能直接注入实例,它必须向实例注入提供程序: 问题是,上面的FooPrime注入不是注入名为“prime”的实例,而是注入名为“prime”的提供者,这当然不是我想要的。 如何让Guice为名为“prime”的Foo实例注入一个提供程序?

  • 我正在使用OBIEE 12c进行BI分析。通过创建MSAD\U提供程序在WebLogic中设置LDAP身份验证。 安全领域- 在配置下- 控制标志=足够 在配置下- 连接 主机:ldap1。领域com ldap2。领域通用域名格式 端口:389 负责人:对用户和组信息具有管理/读取权限的AD用户。 凭据:上面指定的主体用户的密码。 用户 用户库DN:所有用户都存在的OU。 所有用户过滤:( 来自名