我正在使用OSGi作为我工作中的最新项目,就模块化和功能而言,它非常漂亮。
但我对开发工作流程并不满意。最终,我计划在依赖图中安排30-50个独立的捆绑包 - 据说,这就是OSGi的设计目标。但我无法找到一种在编译时间管理依赖关系的简洁方法。
示例:您有捆绑包A和B. B依赖于A中定义的包。每个捆绑包都是作为单独的Java项目开发的。
为了编译B,A必须在javac类路径上。
你是:
没有。 5听起来最干净,但也有很多开销。
答案 0 :(得分:7)
我的公司有100多个捆绑项目,我们使用Eclipse来管理依赖项。但是,我不建议使用“必需的插件”方法来管理依赖项。最好的办法是创建插件项目。仅导出要显示的每个项目的包。然后在导入端执行以下操作:
打开清单编辑器
转到依赖关系选项卡左下角是一个名为“自动管理依赖关系”的部分
添加当前插件所依赖的任何插件
编写代码后,可以单击该选项卡上的“添加依赖关系”链接以自动计算导入的包。
如果从Eclipse运行,则在执行时会自动完成。
这种方法的好处是你的构建包只使用OSGi定义的包导入/导出机制,而不是Eclipse中的东西。
如果您想了解更多信息,我建议您访问此网站并订购该图书。这很棒。
答案 1 :(得分:5)
好吧,做你应该拥有的很长时间,单独的实现和API ......好吧,这在现有系统上并不总是那么容易,但是这个模型有很大的优势。一旦你的API在一个单独的(更稳定的)bundle / jar中,你就可以针对该bundle / jar编译客户端和实现。
成功捆绑的一个关键特质是它尽可能少地假设外部世界。这意味着您不必针对在运行时运行的bundle进行编译,我倾向于不努力不这样做。您应该只针对bundle最小的依赖项集进行编译。如果做出假设,则它们显式为导入的包和服务的使用。设计良好的OSGi系统尝试将服务用于所有的捆绑间通信。这个模型不仅摆脱了类加载问题,而且还使您的构建设置更加分离。
不幸的是,大多数代码都是作为具有相当宽的接口的库编写的,因为它们手动编写了许多服务提供的功能,如工厂和监听器。此代码在实现和API之间存在紧密关系,因此在编译期间和OSGi中必须在类路径上具有相同的代码。这个问题的一个解决方案是使用它在bundle中包含这种代码(但要确保没有这个库的对象泄漏到其他bundle)。一点额外的内存消耗,但它可以让您免于一些麻烦。
因此,使用OSGi,尝试创建依赖服务的系统,并针对其服务API进行编译,而不是实现包。
答案 2 :(得分:2)
基本上,您可以使用:
但是,由于二进制依赖更清晰,它也是由maven等发布管理框架最好地管理的依赖类型。
您可以通过 m2eclipse 将maven集成到Eclipse项目中。
要使用的Maven插件将是: maven-bundle-plugin ,您可以在以下位置查看:
使用Felix的Log Service实现来考虑这个更现实的例子 Log Service项目由一个包组成:
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>
答案 3 :(得分:2)
有一个第6个选项,我用于几个项目,即使用单个Eclipse项目(不是插件项目,而只是一个普通的Java项目)并将所有源代码放在那里。与项目关联的构建文件将简单地在一次传递中编译所有代码,然后从编译的类中创建bundle(使用Ant中的Bnd或即将发布的BndTools)。
这有一个缺点,它不尊重开发和编译时的可见性,但它的优点是它是一个非常简单的开发模型,可以为您提供非常快速的构建和部署时间。