gpt4 book ai didi

java - 如何选择合适的服务实现?

转载 作者:行者123 更新时间:2023-11-30 02:50:03 24 4
gpt4 key购买 nike

我创建了一个具有多个实现的服务,如下所示:

@ProviderType
public interface MyService {
public void printMessage();
}

@Component
public class Foo implements MyService {
public void printMessage() {
System.out.println("foo");
}
}

@Component
public class Bar implements MyService {
public void printMessage() {
System.out.println("bar");
}
}

真正的实现显然要复杂一些(我不能只做一个 printMessage 接受参数的实现!)。服务的使用者需要能够根据属性选择适当的实现 - 为简单起见,我们可以假设我正在使用实现的名称。

现有的非 OSGi 实现使用的工厂方法是这样的:

public MyService getService(String property) {
switch (property) {
case "ham":
return new Foo();
case "spam":
return new Bar();
}
}

真正的实现同样更加复杂(它基于 property 参数的子字符串匹配)。 (对我来说)将其转换为 OSGi 的最简单方法是将此工厂方法转换为 MyService 的静态方法,仅返回必要的过滤字符串,并让消费者处理繁琐的部分获取 BundleContext,然后获取和取消获取服务:

public class MyConsumer {
private BundleContext context;

@Activate
public void activate(BundleContext context) {
this.context = context;
}

public void doStuff() {
Collection<ServiceReference<MyService>> refs = context.getServiceReferences(MyService.class, MyService.getService("ham"));
ServiceReference<MyService> service = refs.iterator().next();
context.getService(service).printMessage();
context.ungetService(service);
}

是否有更好的方法来创建一个返回“服务”的“工厂”,但不需要消费者处理 BundleContexts 等?

我发现了一些不太有效的方法:

  • @Reference(target = "ham")(我知道语法是错误的)允许我根据属性选择实现,但仅限于编译时。
  • ServiceFactory 允许不同的包获取服务的不同实例,但不指定实现。

最佳答案

服务的理念是消费者不应该选择,因为这使得消费者非常不可重用。如果将控制权转移给消费者,通常会使系统变得脆弱。消费者应该使用注册的任何内容。

一种反模式是您尝试隐藏服务的实现,但随后需要在使用者中进行特定的实现。如果这是您的用例,那么您的实现是公开的,只需将其设为自己的服务类型即可。当然也可以注册为普通的MyService类型,也可以注册多种类型。

如果您有要使用的外部选择标准,例如一台打印机,并且您希望用户决定,然后您只需获取所有内容并将其显示给用户即可。使用服务 ID,您可以使用正确的服务 ID。

如果您需要配置应使用哪个服务,则应使用@Reference(target="(selection.criterium=foo)")。您可以使用配置管理来覆盖此选择。 targets对此进行了解释。 。您基本上可以使用引用名称后跟 .target 来设置所需过滤器的属性。

关于java - 如何选择合适的服务实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38986643/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com