OSGI学习之二: HelloWorld

不可免俗,一律HelloWorld!

因为OSGI有三层,module,lifecycle,service,所以我们用三个helloworld来演示三个层。

1.Module Layer:

Module层没有代码要写,只是将代码打包到bundle。

比如,我们要将下边这个类放到bundle里。

package org.foo.hello;
public class Greeting {
final String m_name;
public Greeting(String name) {
   m_name = name;
}
public void sayHello() {
  System.out.println("Hello, " + m_name + "!");
}
}


将这个类导出到org.foo.hello.jar,并在这个jar的META-INF/MANIFEST.MF文件里添加

Bundle-ManifestVersion: 2
Bundle-Name: Greeting API
Bundle-SymbolicName: org.foo.hello
Bundle-Version: 1.0
Export-Package: org.foo.hello;version="1.0"

 

对于想要使用上边创建的这个bundle的bundle,需要在它的jar包的META-INF/MANIFEST.MF里添加

Bundle-ManifestVersion: 2
Bundle-Name: Greeting Client
Bundle-SymbolicName: org.foo.hello.client
Bundle-Version: 1.0
Import-Package: org.foo.hello;version="[1.0,2.0)"

可以看到一个是export,一个是import。

2.Lifecycle层

如果一个bundle需要做一些初始化工作,比如连接数据库,这时lifecycle层就有用武之地了。Bundles可以顶一个 activator,这个可以让我们介入到一个bundle的生命周期里。这个后来会详细再说,现在先看看这货大概怎么工作。下边这个是一个单例模式的greeting类。

package org.foo.hello;
public class Greeting {
static Greeting instance;
final String m_name;
Greeting(String name) {
  m_name = name;
}
public static Greeting get() {
  return instance;
}
public void sayHello() {
  System.out.println("Hello, " + m_name + "!");
}
}

它在使用前需要调用构造函数来初始化name参数。我们看一下如何利用activator来初始化:

package org.foo.hello;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
public void start(BundleContext ctx) {
  Greeting.instance = new Greeting("lifecycle");
}
public void stop(BundleContext ctx) {
  Greeting.instance = null;
}
}

start和stop都是接口BundleActivator的方法,还有方法的参数BundleContext,是一个重要的参数,后面会详细讲,这货就是你的bundle和整个OSGI系统交互用的。

这个例子就是让你知道一个bundle可以介入自己的lifecycle,而且可以和整个OSGI framework交互。

另外你需要在你的META-INF/MANIFEST.IM里加上

Bundle-Activator: org.foo.hello.Activator
Import-Package: org.osgi.framework

这样OSGI framework就知道你有了自己的activator了。

3.Service层

service层是基于接口的实现方式,比如

接口:

package org.foo.hello;
public interface Greeting {
  void sayHello();
}

OK,下边是实现

package org.foo.hello.impl;
import org.foo.hello.Greeting;
public class GreetingImpl implements Greeting {
final String m_name;
GreetingImpl(String name) {
  m_name = name;
}
public void sayHello() {
  System.out.println("Hello, " + m_name + "!");
}
}

没啥嘛,这个OSGI有个毛关系,别急,只要你平时就是面向接口编程的。改动不大,要做的就是如何注册你的服务到OSGI,和怎样从OSGI查询已经注册的服务。
所有的服务实现最终都被打包到一个bundle里,这个bundle必须添加自己的lifecycle响应以有机会注册自己的服务。就是说你必须实现自己的activator。LOOK:

package org.foo.hello.impl;
import org.foo.hello.Greeting;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
public void start(BundleContext ctx) {
  ctx.registerService(Greeting.class.getName(),
    new GreetingImpl("service"), null);
}
public void stop(BundleContext ctx) {}
}

看看在start方法里都干了些什么?bunldecontext,注册服务,第一个参数服务实现的接口名,接着是服务实现的实例,最后是service property。
stop的时候OSGI会帮你注销任何这个bundle注册的服务。

这是注册一个服务,那么怎么查找一个服务呢?

package org.foo.hello.client;
import org.foo.hello.Greeting;
import org.osgi.framework.*;
public class Client implements BundleActivator {
public void start(BundleContext ctx) {
  ServiceReference ref =
  ctx.getServiceReference(Greeting.class.getName());
  ((Greeting) ctx.getService(ref)).sayHello();
}
public void stop(BundleContext ctx) {}
}

好了就这样,这里没有考虑找不到服务的情况。

这里我们可以看到得到一个service分两步,第一步是获取一个service的reference。用这个reference再去得服务。

 这个是因为service可以随时被注销,你直接引用阻止jvm的垃圾回收。

posted @ 2012-08-02 17:56  mark_xue  阅读(1611)  评论(0编辑  收藏  举报