Skip to content
Iacob edited this page Nov 8, 2010 · 1 revision

Apache Felix示例教程一 —— 用于监听服务事件的程序包

本示例程序创建了一个简单的程序包来监听OSGi服务的事件。本示例程序起初并没有做太多事情,因为它做的仅仅是打印出注册和注销服务的一些详细情况。在下一个示例程序中我们会创建并且实现一个让这个程序包做一些实际事情的服务,现在我们仅仅使用此例帮助我们理解创建一个程序包的基本步骤。

一个程序包通过一个唯一的BundleContext(译者注:程序包运行的上下文环境)实例访问OSGi框架。为了获取程序包运行的上下文环境,它必须实现BundleActivator接口,这个接口有两个方法:start()和stop(),它们都会接收程序包的上下文而且在程序包启动和停止的时候被分别调用。在下面的代码里,我们的软件包实现了BundleActivator接口而且使用上下文环境将其自己添加为监听服务事件的监听器。(我们的程序称为Activator.java)

Toggle line numbers

1 /* 2 * Apache Felix OSGi 教程. 3 / 4 5 package tutorial.example1; 6 7 import org.osgi.framework.BundleActivator; 8 import org.osgi.framework.BundleContext; 9 import org.osgi.framework.ServiceListener; 10 import org.osgi.framework.ServiceEvent; 11 12 / 13 * 这个类实现了一个简单的利用OSGi框架的事件机制监听服务事件的程序包。当 14 * 接收到服务事件时,它会打印出事件的详细信息。 15 / 16 public class Activator implements BundleActivator, ServiceListener 17 { 18 / 19 * 实现BundleActivator.start()。打印一条消息并且将其自身作为一个服务监听器注册 20 * 到程序包运行的上下文环境中。 21 * @param context 程序包运行时在框架中所处的上下文环境 22 / 23 public void start(BundleContext context) 24 { 25 System.out.println("Starting to listen for service events."); 26 context.addServiceListener(this); 27 } 28 29 / 30 * 实现BundleActivator.stop()。打印一条信息并且将其自身作为 31 * 一个服务监听器从程序包运行的上下文环境中移除。 32 * @param context 程序包运行时在框架中所处的上下文环境 33 / 34 public void stop(BundleContext context) 35 { 36 context.removeServiceListener(this); 37 System.out.println("Stopped listening for service events."); 38 39 // Note: It is not required that we remove the listener here, 40 // since the framework will do it automatically anyway. 41 } 42 43 / 44 * 实现ServiceListener.serviceChanged()。打印出框架中的任何服务事件的详细信息。 45 * @param event 发生的服务事件 46 **/ 47 public void serviceChanged(ServiceEvent event) 48 { 49 String[] objectClass = (String[]) 50 event.getServiceReference().getProperty("objectClass"); 51 52 if (event.getType() == ServiceEvent.REGISTERED) 53 { 54 System.out.println( 55 "Ex1: Service of type " + objectClass[0] + " registered."); 56 } 57 else if (event.getType() == ServiceEvent.UNREGISTERING) 58 { 59 System.out.println( 60 "Ex1: Service of type " + objectClass[0] + " unregistered."); 61 } 62 else if (event.getType() == ServiceEvent.MODIFIED) 63 { 64 System.out.println( 65 "Ex1: Service of type " + objectClass[0] + " modified."); 66 } 67 } 68 }

在为此程序包编写了Java代码之后,我们必须定义一个包含OSGi框架处理此程序包所需的导引信息的描述(manifest)文件。此描述文件和与程序包相关的Java类一起包装在一个JAR存档文件中。我们创建一个名为manifest.mf包含如下信息的文件(译者注:此文件就是上文中提到的描述文件):

Bundle-Name: Service listener example Bundle-Description: A bundle that displays messages at startup and when service events occur Bundle-Vendor: Apache Felix Bundle-Version: 1.0.0 Bundle-Activator: tutorial.example1.Activator Import-Package: org.osgi.framework

以上导引信息中大部分是直接提供给维护者的资料。只有Bundle-Activator和Import-Package导引信息是被框架直接使用的。Bundle-Activator属性告知框架哪个类实现了BundleActivator接口。根据此条信息,当OSGI框架启动时,指定的类的实例被创造出来并且其start()方法被调用。同样,当框架停掉这个软件包的时候其stop()方法会被调用。Import-Package属性告诉框架此软件包依赖的外部软件包,所有包含activator的软件包必须引入 org.osgi.framework,因为其包含OSGi核心类的定义。任何软件包依赖关系都会被OSGi核查而且选中。(提示:确信你的 manifest文件尾部以回车结束,否则最后一行会被忽略)

现在我们需要编译这个源文件。编译这个源文件时我们需要在classpath中加入felix.jar文件(可以在felix套件的bin目录下找到),我们用下面的命令编译源文件:

javac -d c:\classes *.java

此命令会编译所有的源文件并且把生成的类文件输出到c:\classes目录中一个子目录下,这个子目录就是tutorial\example1,按照我们在源文件中制定的包名命名。为了让以上命令能够正常执行,目录c:\classes必须存在。编译后,我们必须创建一个JAR文件以包装生成的包目录,且要将包含软件包索引信息的描述文件一并添加到JAR包中。我们使用如下命令创建这个JAR文件。

jar cfm example1.jar manifest.mf -C c:\classes tutorial\example1

此命令利用我们创建的描述文件创建了一个JAR包而且包含了在c:\classes目录下的tutorial\example1目录中所有的类文件。当此JAR文件成功创建后,我们便可以准备安装并且启动此程序包。

我们按照usage.html中描述的步骤启动Felix,当我们启动Felix后,程序会询问一个档案名,我们可以将我们所有的程序包置入一个名为"tutorial"的档案中。现在我们可以安装并启动我们的程序包。例如我们将我们的的程序包创建在c:\tutorial下,我们可以使用下面的命令安装并启动它:

start file:/c:/tutorial/example1.jar

上述命令可以在一个步骤里安装并启动这个软件包,同时也可以使用install和start两个命令分两步安装并启动此软件包。如果要停掉此程序包,可以使用Felix的stop命令,需要注意的是,这个程序包并没有做什么实际的事情,因为它只是监听服务事件而且我们也没有注册任何服务。在下一个例子中我们会注册一个服务来发送事件让这个程序包去接收。如果想要离开Felix,使用shutdown命令。

Clone this wiki locally