代码之家  ›  专栏  ›  技术社区  ›  stacker

OSGi包和组件有什么区别?

  •  13
  • stacker  · 技术社区  · 15 年前

    开始使用OSGi时,我想知道捆绑包和组件之间的概念差异是什么。以及何时使用它们中的哪一个。欢迎指点。

    编辑:

    组件和包提供不同的接口,因此它们可能不可互换。

    2 回复  |  直到 15 年前
        1
  •  5
  •   omerkudat    15 年前

    在OSGi术语中,“组件”类似于运行时服务。每个组件都有一个实现类,并且可以选择性地实现一个公共接口,有效地提供这个“服务”。OSGi的这一方面有时类似于服务注册模式。

    根据定义,OSGi中的组件由一个包提供。捆绑包可以包含/提供多个组件。虽然捆绑包本身可能不提供服务,但是组件/声明性服务用于使OSGi更加面向服务。您没有义务使用组件/服务。

        2
  •  10
  •   Community Mohan Dere    8 年前

    component 是:

    • 系统中的活动参与者
    • 了解并适应环境
      • 环境=其他组件提供的服务
      • 环境=资源、设备…
    • 可以向其他组件提供服务,也可以使用其他组件提供的服务
    • 拥有生命周期

    简而言之:

    • 组件提供服务
    • 捆绑管理生命周期

    一个包只能有一个激活器(需要 BundleContext ,可以有任意多个活动组件。
    这意味着您最终可能会尝试将几个松散相关的关注点放入一个类中。
    这就是为什么它可能更容易管理 those components by Declarative Services 通过 the SCR (服务组件运行时,它是一个“扩展包”,实现了新的和改进的OSGiR4.2DS——声明性服务——规范)。
    这在OSGi4.2之后尤其如此,因为现在将DS组件编写为pojos要容易得多: activate deactivate 方法不再需要 ComponentContext 参数。也见 Lazy Declarative Service .


    注:

    它有助于在OSGi的上下文中替换这些术语,并查看“我们是如何做到这一点的”。( excellent blog post by Neil Bartlett )

    下面是一些相关的摘录,其中“模块”最终是OSGi包(管理声明服务的组件):

    模块分离

    我们的首要要求是 干净地分离模块,使来自一个模块的类不具有从其他模块看到和隐藏类的不受控制的能力。 .
    在传统的Java中,所谓的A.y.Cl类路径是一个庞大的类列表,如果多个类恰好具有相同的完全限定名,那么第一个将总是被找到,而第二个和所有其他类将被忽略。

    防止类的不受控制的可见性和模糊性的方法是为每个模块创建一个类加载器。类加载器只能直接加载它知道的类,在我们的系统中,这些类将是单个模块的内容。

    模块访问级别

    如果我们停在这里,那么模块将完全隔离,并且无法相互通信。为了使系统实用,我们需要重新添加在其他模块中查看类的能力,但是我们以一种谨慎和受约束的方式进行。
    此时,我们输入另一个需求: 模块希望能够隐藏一些实现细节。

    我们希望有一个__module_访问级别,但现在的问题是javac编译器不知道模块边界在哪里。

    我们在模块系统中选择的解决方案是允许模块仅导出其内容的一部分。如果某个模块的某些部分未导出,那么其他模块就无法看到它。

    在导入时,我们应该导入实际需要使用的内容,不管它来自何处,并忽略所有与之一起打包的内容。

    进出口粒度

    OSGi选择软件包。
    Java包的内容是有点连贯的,但是将包封装为导入和导出并不太繁琐,而且它不会破坏任何东西,将一些包放在另一个模块中的一个模块和其他包中。
    应该是模块内部的代码可以放在一个或多个未导出的包中。

    封装布线

    现在我们有了一个模块如何隔离自己然后重新连接的模型,我们可以想象构建一个框架来构造这些模块的具体运行时实例。它将负责安装模块,并构建了解各自模块内容的类加载器。

    然后,它将查看新安装模块的导入,并尝试查找匹配的导出。

    这样做的一个意想不到的好处是我们可以动态地安装、更新和卸载模块。安装新模块对已经解析的模块没有任何影响,尽管它可能会使一些以前无法解析的模块得以解析。在卸载或更新时,框架确切地知道哪些模块受到影响,如果需要,它将改变它们的状态。

    版本

    我们的模块系统看起来不错,但是我们还不能处理随着时间推移不可避免地在模块中发生的变化。我们需要支持版本。

    我们该怎么做?首先,导出者可以简单地说明一些关于其正在导出的包的有用信息:这是API的1.0.0版本。导入程序现在只能导入与预期兼容、编译/测试过的版本,并且拒绝接受

    打包模块和元数据

    我们的模块系统需要一种方法来打包模块的内容,以及描述导入和导出到可部署单元的元数据。

    所以唯一的问题是,我们应该把元数据放在哪里,即导入和导出的列表、版本等等?

    碰巧OSGi是在2000年之前设计的,所以它选择了其中的一种解决方案。相反,它回顾了JAR文件规范,其中给出了答案:
    META-INF/MANIFEST.MF 是任意特定于应用程序的元数据的标准位置。

    晚绑定

    模块化难题的最后一个部分是实现到接口的后期绑定。我认为这是模块化的一个关键特性,即使一些模块系统完全忽略了它,或者至少认为它超出了范围。

    我们应该找一个 分散式方法 .
    让我们假设每个模块都可以简单地创建对象,并将它们发布到其他模块可以找到的地方,而不是被上帝类告知要做什么。我们称这些已发布对象为__services_,它们的发布位置为__service registry_。
    关于服务的最重要的信息是它实现的接口,因此我们可以将其用作主注册密钥。
    现在,一个需要查找特定接口实例的模块可以简单地查询注册表并找出当时可用的服务。注册表本身仍然是任何模块外部存在的中心组件,但它不是__God______,而是像一个共享的白板。