OSGi一小步–声明式服务

OSGi声明式服务是个好东西,有点依赖注入的味道,开发人员以配置的方式去注册或引用服务,你不需要为注册服务而单独写一个BundleActivator了,省去手工注册的繁琐。下面写一个例子改造上一篇代码的运行方式。

改造hello.service.consumer

去掉HelloServiceConsumer对BundleActivator的实现,变成一个非常普通的java类,部分代码如下:

//引用被注入的服务

private HelloService helloService;

//当组件变为satisfied时,该方法将被调用

public void activate(ComponentContext context) {

executor = Executors.newFixedThreadPool (1);

executor.execute(new HelloServiceVisitorTask());

System.out .println(“HelloServiceConsumer activate”);

}

//当组件变为unsatisfied时,该方法将被调用

public void deactivate(ComponentContext context) {

executor.shutdownNow(); //关闭服务访问线程

executor = null ;

System.out .println(“HelloServiceConsumer deactivate”);

}

//当SCR(Service Component Runtime)发现容器中注册有HelloService服务时,该方法将被

//调用,相当于注入helloService实例,该方法在组件激活前调用

public void setHelloService(HelloService helloService) {

System.out .println(“setHelloService”);

synchronized (helloServiceLock) {

if (this .helloService != helloService) {

this .helloService = helloService;

}}}

//当提供HelloService服务的组件变为不可用时,该方法将被调用,相当解绑引用

public void unsetHelloService(HelloService helloService) {

synchronized (helloServiceLock) {

if (this.helloService == helloService) {

this.helloService = null;

}}}

在src/main/resources目录下建立OSGi-INF目录,用来存放组件描述xml文件,内容如下:

<?xml version=”1.0″ encoding=”UTF-8″?>

<component name=”HelloServiceConsumerComponent”>

<!– 该组件没有提供服务 –>

<implementationMsoNormal” align=”left” style=”text-align:left;mso-layout-grid-align: none;text-autospace:none”>    <!–  引用服务  –>

<reference name=”HelloServiceComponent” interface=”org.lazyman.study.osgi.service.HelloService”

bind=”setHelloService” //绑定服务的方法

unbind=”unsetHelloService” //解绑服务的方法

//表示要求容器中存在HelloServiceComponent的个数,该参数影响组件的激活策略

cardinality=”0..1″

//在不调用deactivate情况重新绑定新的服务

policy=”dynamic” />

</component>

最后我们需要在MANIFEST.MF文件里增加新的头:

Service-Component: OSGi-INF/consumer.component.xml

改造hello.service.impl

去掉HelloServiceActivator类,增加hello.service.component.xml组件描述文件,内容如下

<?xml version=”1.0″ encoding=”UTF-8″?>

<component name=”HelloServiceComponent”>

<service>

// 表明提供org.lazyman.study.osgi.service.HelloService服务

<provide  interface=”org.lazyman.study.osgi.service.HelloService” />

</service>

// 服务实现类

<implementation />

</component>

同样需要在MANIFEST.MF文件里增加新的头:

Service-Component: OSGi-INF/hello.service.component.xml

部署运行

想激活基于服务的组件功能,需要增加如下bundle,可以去equinox网站下载

org.eclipse.equinox.ds    //提供SCR功能

org.eclipse.equinox.util  // ds的依赖

org.eclipse.osgi.services //osgi各种服务api

并且org.eclipse.equinox.ds bundle 必须在自定义bundle启动前启动,如下状态所示

Framework is launched.

id      State       Bundle

3       RESOLVED    hello.service.consumer_1.0.0

4       RESOLVED    hello.service.impl_1.0.0

5       RESOLVED    hello.service_1.0.0

6       RESOLVED    org.eclipse.equinox.ds_1.1.1.R35x_v20090806

7       <<LAZY>>    org.eclipse.equinox.util_1.0.100.v20090520-1800

8       RESOLVED    org.eclipse.osgi.services_3.2.0.v20090520-1800

启动 org.eclipse.equinox.ds bundle

start 6

id      State       Bundle

3       RESOLVED    hello.service.consumer_1.0.0

4       RESOLVED    hello.service.impl_1.0.0

5       RESOLVED    hello.service_1.0.0

6       ACTIVE      org.eclipse.equinox.ds_1.1.1.R35x_v20090806

7       ACTIVE      org.eclipse.equinox.util_1.0.100.v20090520-1800

8       RESOLVED    org.eclipse.osgi.services_3.2.0.v20090520-1800

分别启动5  4  3,可以看到如下结果

osgi> start 3

setHelloService //先调用服务绑定方法

HelloServiceConsumer activate //激活HelloServiceConsumerComponent

HelloService //调用服务接口方法的输出

该文总结了自己对OSGi声明式服务的学习历程,利用好这个功能可以让生活变得更加有趣!

目前启一个bundle都是手动start的,似乎有些麻烦,下篇将展示如何通过程序轻松启动所有bundle


–OSGi Declarative Services相关概念可以参见这篇文章(http://www.ibm.com/developerworks/cn/opensource/os-ecl-osgids/index.html )

你可能感兴趣的:(osgi)