Welcome 微信登录

首页 / 软件开发 / JAVA / 模块化Java:静态模块化

模块化Java:静态模块化2011-03-29 infoq Alex Blewitt 译:宋玮模块化是大型Java系统的一个重要特征。在这些项目中构建脚本和项目通常被划分为 多个模块,以便改进构建过程,但是在运行时却很少考虑划分模块的问题。

在“模块化Java”系列文章的第二篇里,我们将讨论静态模块化(static modularity )。内容包括如何创建bundle、将其安装到OSG引擎以及怎样建立bundle之间的版本依赖 。在下一篇文章中,我们将讨论动态模块化(dynamic modularity)并展示bundle如何对 其他bundle作出响应。

在上篇文章《模块化Java简介》中讲到,Java在开发时把package作为模块化单元,部 署时把JAR文件作为模块化单元。可是尽管像Maven这样的构建工具能够在编译时保证 package和JAR的特定组合,但这些依赖在运行时classpath下仍可能出现不一致的情况。 为了解决这一问题,模块可以声明其依赖需求,这样,在运行时就可以在执行之前进行依 赖检查。

OSGi是一个Java的运行时动态模块系统。OSGi规范描述了OSGi运行时的工作行为方式 ;当前版本是OSGi R4.2。

一个OSGi模块(也称为bundle)就是一个普通的JAR文件,但在其MANIFEST.MF中带有 附加信息。一个bundle的manifest必须至少包含如下内容:

Bundle-ManifestVersion:对OSGi R4 bundle来说必须是2(OSGi R3 bundle则默认为 1)

Bundle-SymbolicName:bundle的文本标识符,通常以反向域名的形式出现,如 com.infoq,并且往往对应了包含其中的package

Bundle-Version:major.minor.micro.qualifier形式的版本号,前三个元素是数字( 缺省是0),qualifier则是文本(缺省是空字符串)

创建一个bundle

最简单的bundle必须在manifest文件中包含如下内容:

Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.infoq.minimal
Bundle-Version: 1.0.0

创建bundle并没有什么可稀奇的,那么让我们创建一个带activator的bundle吧。下面 是OSGi特定的代码片段,在bundle启动时被调用,有点像是bundle的main方法。

package com.infoq;
import org.osgi.framework.*;
public class ExampleActivator implements BundleActivator {
public void start(BundleContext context) {
System.out.println("Started");
}
public void stop(BundleContext context) {
System.out.println("Stopped");
}
}

为了让OSGi知道哪个类是activator,我们需要在manifest中加入额外的信息项:

Bundle-Activator: com.infoq.ExampleActivator
Import-Package: org.osgi.framework

Bundle-Activator声明了在bundle启动时要实例化并调用其start()方法的类;类似的 ,在bundle停止时将调用该类的stop()方法。

那么Import-Package又是干什么的?每个bundle都需要在manifest中定义其依赖,以 便在运行时判断所有必需代码是否可用。在本例中,ExampleActivator依赖于 org.osgi.framework包中的BundleContext;如果我们不在manifext中声明该依赖,在运 行时就会碰到NoClassDefFoundError错误。