首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用 OSGi 应用程序开发和工作的最佳实践 (4)

用 OSGi 应用程序开发和工作的最佳实践 (4)

6. 共享服务而是不实现开发 OSGi bundle 时,一个最佳实践是使用 OSGi 服务注册表来实现工厂模式,并用其他 bundle 构造导出类。除了 最佳实践之外,还实现了一个客户端、API 和 API 实现的松耦合。
原因如下
分离 API 和实现的实践从消耗资源的客户端抽象了多个实现。这使得一个供应商的 API 实现可以被另一个替换,且不需要变更使用 API 的客户端。
想要行之有效,对于 API 和实现的分离,客户端需要一个机制来获取一个实现实例,而无需知道将要使用哪个实现。在非 OSGi 系统中,这通常是由一个 API 类中的静态工厂方法来完成的。静态工厂方法从类路径上的实现中选择要实例化哪个实现。由于平面类空间的所有这些实现都是可视的。用于决定哪个类应该被实例化的算法是特定于 API 的。
这个机制在 OSGi 中不能正常工作,因为含有 API 类的 bundle 不能看到任何含有 API 实现的 bundle。
OSGi 以 OSGi 服务注册表的形式提供一个更为整洁的解决方案。Bundle 含有以下 API 实现之一:
  • 在 OSGi 服务注册表中注册一个 API 接口实例。这可以产生这种效果,即所有客户端 bundle 仅使用一个实现实例。
  • 在 OSGi 服务注册表中注册一个 OSGi ServiceFactory 接口。ServiceFactory 接口在请求一个服务实例时为 OSGi 所用。在这种情况下,ServiceFactory 可以选择实例来返回到每个请求客户端 bundle。例如,可以向所有的请求客户端 bundle 返回同一个实例,或可以返回不同的实例,或两者兼而有之。
客户端是完全从实现中分离出来了,正如在静态工厂方法模式中那样。此外:
  • API 是完全从所有实现中分离出来了,正如 OSGi 服务层与实现合作应对实例创建。
  • 用于决定哪个实现将要返回的算法是贯穿所有 API 的而不是特定于某一个 API,就像在非 OSGi 系统中使用的静态工厂方法模式那样。
OSGi 服务注册表是一个共享服务的动态机制,其中服务可以在运行时自由来往。在服务可用时,Blueprint 通过将一个请求服务注入客户端 bundle 的 bean 中,帮助客户处理这种动态性。服务不可用时,Blueprint 可以注入另一个实现(如果有一个已注册的)。
7. 好的 bundle 就像构造良好的类:松耦合、高聚合编写 bundle 时,将功能限制到一个特定的任务。将一个 bundlle 执行的任务数量降到最低,尝试尽量少的依赖。
原因如下
编写一个 OSGi 应用程序时,总想向一个已有 bundle 添加更多的功能,而不是去编写一个新的 bundle 。然而,这很快就会产生一个大且聚合性低的 bundle,通常会导致 bundle 导入和导出大量的包。使用 Require-Bundle 头部隐藏大量包导入并不是一个好的实践,因为这只不过是在 bundle 之间添加紧耦合。随着 bundle 依赖图的增长,必须下载和安装的 bundle 数量不断增多,通常成指数增长。这称之为 “hairball 效应” 。一个设计不佳的 bundles 需要在您的应用程序中下载并安装数十甚至上百兆,而仅仅能访问一到两个简单的功能,而一个高聚合的 bundle 只有极少的依赖性,一个很小的依赖树,而且更容易在其他应用程序中重用。需要注意该最佳实践为面向类设计对象镜像最佳实践,这是因为同样的理由。一个 OSGi bundle 应该是封装良好、高度聚合和松耦合的 — 就像一个格式良好的类 — 防止其依赖特定版本的其他 bundle 或类,并增加重用机会。
示例
一个设计不佳的示例是一个登录实现,使用户可以登录文件系统、通过 JPA 登录数据库,或登录一个消息队列(图 9)。为了使用文件系统 logger,一个应用程序需要加载消息 API、JAP API,等等。因此,应用程序含有 logger 实现类,但并不使用。一个比较好的解决方案是登录接口和各个实现相互分离(图 10)。通过这种方式,应用程序可以选择包含一个它使用的登录 bundle ,而不包括额外实现类和任何进一步实现,这些都出现在登录 bundle 中。
图 9. 一个不良设计系统,其中一个 bundle 提供一个 API 的多个实现图 10.  一个设计良好的系统,其中一个 API 的每个实现都由一个独立的 bundle 提供
返回列表