【问题标题】:What is a reasonable OSGi development workflow?什么是合理的 OSGi 开发工作流程?
【发布时间】:2010-05-04 20:53:06
【问题描述】:

我正在将 OSGi 用于我最新的工作项目,就模块化和功能而言,它非常漂亮。

但我对开发工作流程不满意。最终,我计划有 30-50 个独立的包,排列在一个依赖图中——据说,这就是 OSGi 的设计目的。但是我想不出在 compile 时管理依赖项的干净方法。

示例:您有包 A 和 B。B 依赖于 A 中定义的包。每个包都作为单独的 Java 项目开发。

为了编译 B,A 必须在 javac 类路径中。

你:

  1. 在 B 的构建脚本中引用项目 A 的文件系统位置?
  2. 构建 A 并将 jar 放入 B 的 lib 目录?
  3. 依赖 Eclipse 的“引用项目”特性并始终使用 Eclipse 的类路径来构建(呃)
  4. 为所有项目使用一个通用的“lib”目录,并在编译后将包 jar 转储到那里?
  5. 设置一个包存储库,从构建脚本解析清单并从存储库中提取所需的包?

没有。 5 听起来最干净,但也需要很多开销。

【问题讨论】:

    标签: java ant compilation osgi


    【解决方案1】:

    我的公司有 100 多个捆绑项目,我们使用 Eclipse 来管理依赖项。但是,我不推荐使用“必需插件”方法来管理依赖项。您最好的选择是创建插件项目。仅从您希望可见的每个项目中导出包。然后在导入端执行以下操作:

    打开清单编辑器

    转到依赖项选项卡左下角是一个名为“依赖项的自动管理”的部分

    添加当前插件依赖的所有插件

    编写完代码后,您可以单击该选项卡上的“添加依赖项”链接来自动计算导入的包。

    如果您从 Eclipse 运行,这会在您执行时自动为您完成。

    这种方法的好处是您构建的包只使用 OSGi 定义的包导入/导出机制,而不是来自 Eclipse 的东西。

    如果您想了解更多信息,我建议您访问此网站并订购这本书。太棒了。

    http://equinoxosgi.org/

    【讨论】:

    • 这是一个更实用的解决方案(我基于 maven 的建议),与 Eclipse PDE 集成。 +1
    【解决方案2】:

    好吧,做你很久以前就应该做的事情,将实现和 API 分开......好吧,这在现有系统上并不总是那么容易,但这种模型对你来说是一笔巨大的收益。一旦您的 API 位于单独的(更稳定的)bundle/jar 中,您就可以针对该 bundle/jar 编译客户端和实现。

    一个成功的捆绑包的关键品质之一是它尽可能少地对外部世界做出假设。这意味着您不必针对在运行时运行的包进行编译,我倾向于尽量不这样做。您应该只针对捆绑包的最小依赖项集进行编译。如果做出假设,它们将明确为导入的包和服务的使用。精心设计的 OSGi 系统尝试将服务用于所有包间通信。此模型不仅消除了类加载问题,还使您的构建设置更加解耦。

    不幸的是,大多数代码都是作为具有相当广泛接口的库编写的,因为它们手动编写了许多服务提供的开箱即用的功能,例如工厂和侦听器。此代码在实现和 API 之间具有紧密的关系,因此您必须在编译期间和 OSGi 中的类路径上具有相同的关系。这个问题的一个解决方案是在使用它的包中包含这种代码(但要确保这个库的对象没有泄漏到其他包)。有点额外的内存消耗,但它可以让你免于一些头痛。

    因此,对于 OSGi,尝试创建依赖于服务的系统并针对其服务 API 进行编译,而不是实现包。

    【讨论】:

      【解决方案3】:

      基本上,你可以使用:

      • 源依赖(使用 Eclipse 的“引用项目”)
      • 二进制依赖(使用bundle A的jar)

      但由于二进制依赖更简洁,它也是由 maven 等发布管理框架管理最好的依赖。
      并且你可以通过m2eclipse将maven集成到你的Eclipse项目中。

      然后要使用的 Maven 插件是:maven-bundle-plugin,您可以在以下位置看到它的实际效果:

      考虑这个使用 Felix 的日志服务实现的更真实的示例。
      日志服务项目由一个单独的包组成:org.apache.felix.log.impl
      它依赖于核心 OSGi 接口以及依赖于特定日志服务接口的纲要 OSGi 接口。以下是它的POM文件:

      <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.log</artifactId>
        <packaging>bundle</packaging>
        <name>Apache Felix Log Service</name>
        <version>0.8.0-SNAPSHOT</version>
        <description>
          This bundle provides an implementation of the OSGi R4 Log service.
        </description>
        <dependencies>
          <dependency>
            <groupId>${pom.groupId}</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>0.8.0-incubator</version>
          </dependency>
          <dependency>
            <groupId>${pom.groupId}</groupId>
            <artifactId>org.osgi.compendium</artifactId>
            <version>0.9.0-incubator-SNAPSHOT</version>
          </dependency>
        </dependencies>
        <build>
          <plugins>
            <plugin>
              <groupId>org.apache.felix</groupId>
              <artifactId>maven-bundle-plugin</artifactId>
              <extensions>true</extensions>
              <configuration>
                <instructions>
                  <Export-Package>org.osgi.service.log</Export-Package>
                  <Private-Package>org.apache.felix.log.impl</Private-Package>
                  <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                  <Bundle-Activator>${pom.artifactId}.impl.Activator</Bundle-Activator>
                  <Export-Service>org.osgi.service.log.LogService,org.osgi.service.log.LogReaderService</Export-Service>
                </instructions>
              </configuration>
            </plugin>
          </plugins>
        </build>
      </project>
      

      【讨论】:

      • 二进制依赖是危险的推荐。上周,我帮助一位客户调试了一个类加载器问题,该问题是由于在 2 个不同的包中具有相同的二进制 jar 的 2 个副本而引起的。当他们试图将二进制 jar 中的对象实例从一个包传递到另一个包时,出现了类转换异常。按照预期使用导入/导出包语句要好得多。在客户的情况下,解决方案是从导出所需包的二进制 jar 制作一个包。然后,两个客户捆绑包都从新捆绑包中导入了他们需要的包。
      • 嗯。我有点希望避免 Mavenizing 整个项目,但我可能无法避免。
      • 这个问题你有后续吗,你是怎么处理的?我有一个非常相似的问题,我通过重新发明 Maven 轮子解决了这个问题。为了避免使用 Maven,我付出了很多努力,最终我得到了一个解决方案,它是 Maven 的一个子集,最终我必须转换为 Maven。项目依赖越复杂,Maven 提供的好处就越多,来自那些真正不喜欢它的复杂性的人。
      【解决方案4】:

      还有第 6 个选项,我已经在多个项目中使用过,即使用单个 Eclipse 项目(不是插件项目,而只是一个普通的 Java 项目)并将所有源代码放在那里。与项目关联的构建文件将简单地一次编译所有代码,然后从编译的类中创建包(使用来自 Ant 的 Bnd 或来自即将发布的 BndTools)。

      它的缺点是它不尊重开发和编译时的可见性,但它的优点是它是一个非常简单的开发模型,可为您提供非常快速的构建和部署时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-16
        • 1970-01-01
        • 2016-04-02
        • 2012-10-29
        • 2017-05-24
        • 1970-01-01
        • 2021-04-15
        • 1970-01-01
        相关资源
        最近更新 更多