OSGI服务与单例模式有什么区别?

13

我是OSGI的初学者,想知道创建OSGI服务与单例模式之间的区别。比如,假设我有一个提供IService的核心(bundle名为core),还有多个需要访问它的bundle。我可以:

  1. core bundle中注册一个服务,插件可以访问该服务
  2. 提供一个单例类,该类提供服务

使用OSGI服务似乎很麻烦;而且由于插件必须依赖于Core(以获取接口),那么使用OSGI服务的优势是什么呢?

4个回答

16

服务是独立模块之间的连接。让模块依赖服务(与其规范包一起)可以显著降低模块之间的耦合,从而为模块化带来很多好处。

我认为单例模式有两种不同的用法:你只想在一组用户之间共享一个对象(例如Log Service),或者确实只能有一个实例(例如只有一个硬件部件)。总的来说,我看到企业软件界大多数人都谈论前一种用法。然而,经验表明,当项目增长时,单例变得不那么单例了,而更像是共享对象,或者至少表面上是共享对象。 OSGi的好处在于,你可以将这两种模式都建模,而“单例”的客户端则对此毫不知情,也不需要一些中央配置。原因是OSGi依赖于负责模块的模块,注册服务是一个局部决策,就像监听服务一样。

服务的力量不在于其动态性(虽然它们很酷,尤其是在开发过程中),服务的本质在于它们提供了完全的本地控制内部模块,而不需要中央配置。一旦你理解了这个强大的功能,就再也回不去了 :-)

最后,OSGi服务并不繁琐,尤其是现在有了带注释的DS。注册服务现在比创建Spring bean要简单得多,没有xml,没有中央配置:


// A component registered as a ISingleton service
@Component
public class MyImpl implements ISingleton {
  void doSingle() { ... }
}

// A component that uses the ISingleton component
@Component
public class MyConsumer {

  @Reference
  void setISingleton(ISingleton is) { ... }
}

...而且这些动态效果几乎是免费的...


7
简短回答:如果您不需要并且也不会需要一个OSGi服务的好处(例如动态管理服务实现和服务搜索),那么您就不需要一个OSGi服务。

但是,考虑的问题远不止于服务是否会很麻烦。 哎呀,OSGi本身就可以被认为是麻烦的。 另一个 bundle 是否需要提供该类的实现? 可能不需要。 核心 bundle 是否会停止运行或无法按需提供实现? 可能会。

要确定服务是否适用于所讨论的类,请阅读OSGi联盟的 What Is OSGi page 上有关服务特定优势的简介。 他们非常好地解释了如何使您的单例类变得比服务更加繁琐。

祝你好运。


谢谢!我会阅读链接并重构代码,使其更加面向服务。 - Adrian Pang
正如我在我的答案中所指出的,一旦您使用DS注释与它们一起使用,我认为OSGi服务并不会有任何麻烦。看看bndtools。 - Peter Kriens

2
我的 OSGi线程模型 的POC让我相信,每个服务对于服务使用者来说都是单例的。因为只有一个服务对象被注册到OSGi服务注册表中(但您也可以覆盖此行为)。因此,在编程方面,单例类和OSGi服务的行为是相同的。您的类级变量在各种服务使用者调用之间共享。
我会说OSGI服务是单例++
但也有区别。OSGi为每个服务提供了单独的类加载器,这在单例中是不可能的。所有{singleton}类都由单个类加载器加载。我们不能在单例中拥有两个具有相同名称(完全限定名称)的类,但在OSGi中却是可能的。
在某些情况下,我们必须确认一个类只应该被加载一次(例如创建 Hibernate 会话工厂、HDFC 服务初始化、POJO 创建等需要重复初始化的任务)。如果你处于 Java EE 场景中,有时你的单例类会被两个不同的类加载器加载两次。这会导致静态块执行两次,是一个不必要的工作。
这种类加载器问题很容易通过 OSGi 处理(考虑到你是初学者,我认为在接下来的几天中类加载本身可能是一个问题)。
OSGi 提供的另一个伟大特性是更新 bundle。假设你更改了单例类中的代码。现在你需要将这个更新后的类部署到正在运行的应用程序中。你实际上需要重新启动系统,以便每个单例类加载器更新单例的新实例。但在 OSGi 中则不需要,只需更新 bundle 即可。
我会说,如果你要设计大型应用程序(企业级),或者如果你需要为有限的硬件容量(低内存约束、低计算能力)设计代码,则选择 OSGi 是最好的选择。对于其他所有情况,普通的 Java 编程就可以完美地工作。

1
您可以管理服务的生命周期(部署新版本、同时运行多个版本等),但是您无法管理单例的生命周期,除非重新启动JVM(即使重启,您在任何时刻也只能使用1个版本)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接