`

Spring与OSGi的整合(转)

 
阅读更多
 

 

1. 开发环境的准备

现在的eclipse都已经包含了Equinox,无需单独下载。
下载最新版的Spring DM,Spring官方网站:www.SpringSource.org
2. 开发OSGi的HelloWorld应用程序

在这一节,我们将开发一个OSGi bundle,演示如何利用Equinox进行OSGi bundle的开发、运行及调试,为之后的示例做准备。
首先,新建一个Plug-in工程

下一步,注意选择目标平台,默认为Eclipse version *,将其改成Equinox,

之后按默认下一步即可,到最后一步时,无需根据模板创建工程,去掉默认的勾,点击完成

可以看到,eclipse为工程自动生成了一个Activator类,如下所示

 

Java代码 复制代码 收藏代码
  1. package helloworld;   
  2.   
  3. import org.osgi.framework.BundleActivator;   
  4. import org.osgi.framework.BundleContext;   
  5.   
  6. public class Activator implements BundleActivator {   
  7.     /*  
  8.      * (non-Javadoc)  
  9.      *   
  10.      * @see  
  11.      * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext  
  12.      * )  
  13.      */  
  14.     public void start(BundleContext context) throws Exception {   
  15.         System.out.println("Hello World!");   
  16.     }   
  17.   
  18.     /*  
  19.      * (non-Javadoc)  
  20.      *   
  21.      * @see  
  22.      * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)  
  23.      */  
  24.     public void stop(BundleContext context) throws Exception {   
  25.     }   
  26. }  
package helloworld;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
	 * )
	 */
	public void start(BundleContext context) throws Exception {
		System.out.println("Hello World!");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
	}
}

 有过eclipse插件开发经验的人应该很快就能明白,这就是该工程——实际上就是上一篇文章中所称的bundle在Equinox平台中的启动入口,相当于我们的熟悉的main函数,如果将该bundle运行到Equinox中,首先进入该bundle的是Activator的start方法,你可以将相关的服务、资源在该方法内完成向bundleContext的注册——文章后面会具体讲到相关内容。在运行期,如果想要该bundle停止运行,Equinox平台将调用Activator的stop方法,你可以在该方法内完成资源的注销等工作。

 

下面我们将要完成首次的Equinox运行,将向大家展现bundle到底是如何运行起来的。为helloworld选择运行方式

弹出对话框

 

在弹出的对话框中,新建一个OSGi Framework运行环境(双击OSGi Framework即可,这里为其取名Equinox),选中helloworld(1.0.0),然后点击右边的Add Required Bundles按钮,eclipse将自动选中运行helloworld的依赖bundle,如果有必要,可以点击右下的Validate Bundles验证按钮,验证程序正常运行所需的bundle是否都被选中,最后点击运行,回到控制台:
osgi> Hello World!
可以看到,之前在Activator的start方法中的输出语句已经被输出到控制台,我们可以通过命令ss查看Equinox的运行情况,可以看到一共运行了两个bundle,如下:
ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.3.R34x_v20081215-1030
1 ACTIVE helloworld_1.0.0
还记得之前讲到过的bundle的几种状态吧?helloworld已经运行起来了。
那么Equinox具体支持哪些命令呢?下表列出了主要的一些命令,如需查看更详细的命令清单,则可以在控制台键入help。

 

类别

命令

含义

控制框架

launch

启动框架

shutdown

停止框架

close

关闭、退出框架

exit

立即退出,相当于 System.exit

init

卸载所有 bundle(前提是已经shutdown)

setprop

设置属性,在运行时进行

控制 bundle

install

安装

uninstall

卸载

start

启动

stop

停止

refresh

刷新

update

更新

展示状态

status

展示安装的 bundle 和注册的服务

ss

展示所有 bundle 的简单状态

services

展示注册服务的详细信息

packages

展示导入、导出包的状态

bundles

展示所有已经安装的 bundles 的状态

headers

展示 bundles 的头信息,即MANIFEST.MF 中的内容

log

展示 LOG 入口信息

其它

exec

在另外一个进程中执行一个命令(阻塞状态)

fork

和 EXEC 不同的是不会引起阻塞

gc

促使垃圾回收

getprop

得到属性,或者某个属性

控制启动级别

sl

得到某个 bundle 或者整个框架的start level 信息

setfwsl

设置框架的 start level

setbsl

设置 bundle 的 start level

setibsl

设置初始化 bundle 的 start level

 

至此,我们已经成功的演示了helloworld,初步了解了OSGi的bundle是如何开发并运行的,下面将进入我们的正题,下面我们将通过一个稍微复杂的示例,讲解bundle之间如何进行包依赖、注册及调用服务

 

 

 

3. 开发一组计算器bundle实例

 

本节讲到的例子是仿照网上甚为流行的一个例子,但苦于一直未找到源码,网上贴的都是一些转帖,代码片段,估计初学者很难将其还原并调通!我最开始弄这个咚咚的时候,其过程之痛苦,难以言喻,所以想着仿照该例子的设计,给予实现,文后贴出源码,希望能帮到大家。
该例子是一个关于计算器的实例,osgi.example.compute bundle(下文简称compute bundle)提供了统一的计算接口:Compute,另外两个bundle分别为osgi.example.compute.add(下文简称add bundle)和osgi.example.compute.multiply(下文简称multiply bundle),在这两个bundle中,各自对compute bundle进行不同的实现,一个实现加法,一个实现乘法。另外还有一个服务消费者osgi.example.compute.consumer bundle(下文简称consumer bundle),consumer bundle负责消费add bundle和multiply bundle提供的服务。上述4个bundle之间的关系

 

创建4个bundle之后的工程目录

 

通过该示例,将演示如何利用Spring DM发布和调用OSGi服务,同时还将演示OSGi的动态服务调用能力。

 

 

3.1. bundle osgi.example.compute

 

compute bundle只提供一个接口——Compute,因此无需依赖更多的bundle,只需最基本的osgi即可。因为不涉及注册资源之类的,所以也无需Activator入口类,这个例子的四个bundles都没用用到Activator接口,实现Acitivator接口的类应该是这个bundle的开启时的入口类,而这里没用用到它,这四个bundle同样可以开启成active状态。
Computer接口源代码如下所示:package osgi.example.compute;

Java代码 复制代码 收藏代码
  1. public interface Compute {   
  2.         public String computeNums(int x, int y);   
  3. }  
public interface Compute {
        public String computeNums(int x, int y);
}

 3.2. bundle osgi.example.compute.add

 

 

add bundle是对compute bundle的具体服务实现,在MANIFEST.MF文件需要引入osgi.example.compute包;当然也可以通过添加依赖bundle的形式,即不引入包,而直接在Required Plug-ins中添加compute bundle。如下图所示,可以看到有Required Plug-ins和Imported Packages两种方式,用Import Packages可能会好一点,至少轻装一点

 

注意:OSGi官方指出,当需要用到其他bundle的类型时,不提倡依赖bundle,应该尽可能采用Import-package的方式引入包,因为依赖bundle可能在加载bundle的时候发生问题。

通过引入osgi.example.compute包,osgi.example.compute bundle被加到了add bundl的classpath当中,解决了开发时期的类型识别问题。
这样一来,在add bundle中就能使用compute bundle中的接口了,Computer接口的实现如下:

 

Java代码 复制代码 收藏代码
  1. package osgi.example.compute.add;   
  2. import osgi.example.compute.Compute;   
  3. public class Add implements Compute {   
  4. public String computeNums(int x, int y) {   
  5. int s = x + y;   
  6. String result = "The Sum is---" + String.valueOf(s);   
  7. return result;   
  8. }   
  9. }  
package osgi.example.compute.add;
import osgi.example.compute.Compute;
public class Add implements Compute {
public String computeNums(int x, int y) {
int s = x + y;
String result = "The Sum is---" + String.valueOf(s);
return result;
}
}

 Compute的实现已经实现了,那么如何将其发布出去呢?这个是由Spring DM负责,Spring DM利用OSGi命名空间下的<service>元素将bean导出为OSGi服务。最简单的形式为:

 

Xml代码 复制代码 收藏代码
  1. <beans:bean id="beanToPublish" class="com.xyz.imp.MessageServiceImp"/>  
  2. <service ref="beanToPublish" interface="com.xyz.MessageService"/>  
<beans:bean id="beanToPublish" class="com.xyz.imp.MessageServiceImp"/>
<service ref="beanToPublish" interface="com.xyz.MessageService"/>
 从示例中可以看出,beanToPublish被service元素声明导出。

另外,service结点还有一些高级属性,如depends-on、context-class-loader、ranking等待,详情请看spring dm reference。
首先,需要在add bundle的工程根目录下的”META-INF”的文件夹下创建一个文件夹,取名”spring”,Spring DM能够自动解析该文件夹下所有的spring配置文件。spring配置文件的具体内容如下所示:<?xml version="1.0" encoding="UTF-8"?>

Xml代码 复制代码 收藏代码
  1. <beans xmlns="http://www.springframework.org/schema/beans"  
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3. xmlns:osgi="http://www.springframework.org/schema/osgi"  
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd   
  5. http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">  
  6. <bean id="addOsgiService" class="osgi.example.compute.add.Add">  
  7. </bean>  
  8. <osgi:service id="addService" ref="addOsgiService"  
  9. interface="osgi.example.compute.Compute">  
  10. </osgi:service>  
  11. </beans>  
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<bean id="addOsgiService" class="osgi.example.compute.add.Add">
</bean>
<osgi:service id="addService" ref="addOsgiService"
interface="osgi.example.compute.Compute">
</osgi:service>
</beans>

 如此一来,其他bundle就能通过spring dm引入接口类型为osgi.example.compute.Compute的服务了,这里的osgi:service标签的id就是服务的名称,就是将bean转为服务的调用时的名称,ref为引用的是哪个bean,而interface指明只要是这个接口的定义处,都可能会用到这个服务,说可能,是因为一个接口的多个实现,也就是有多样的服务来实现,那调用时就取决于spring dm了,spring dm将通过一定的服务查找策略,返回匹配的服务。

 

3.3. bundle osgi.example.compute.multiply

 

该bundle和add bundle相似,在这就不赘述了。

 

3.4. bundle osgi.example.compute.client

 

顾名思义,该bundle将作为add 、multiply两个bundle的客户bundle,演示如何导入服务。
OSGi的测试工作比较麻烦,这方面还没研究,在这里利用spring实例化bean的时期,从构造函数入手,对服务进行测试。Client类的实现很简单,如下所示:

 

Java代码 复制代码 收藏代码
  1. package osgi.example.client;   
  2. import osgi.example.compute.Compute;   
  3. public class Client {   
  4. /**  
  5. * 为了方便测试,采用Spring的构造注入方式,直接在构造函数中调用Compute服务  
  6. * @param compute  
  7. */  
  8. public Client(Compute compute){   
  9. System.out.println(compute.computeNums(56));   
  10. }   
  11. }  
package osgi.example.client;
import osgi.example.compute.Compute;
public class Client {
/**
* 为了方便测试,采用Spring的构造注入方式,直接在构造函数中调用Compute服务
* @param compute
*/
public Client(Compute compute){
System.out.println(compute.computeNums(5, 6));
}
}
 另外,因为client用到了其他几个bundle的类型,所以需要导入相应的包,步骤在3.2一节已有讲到。

spring dm靠<reference>元素来引入服务,最简单的形式如下所示:

 

Xml代码 复制代码 收藏代码
  1. <reference id="beanToPublish" interface="com.xyz.MessageService"/>  
<reference id="beanToPublish" interface="com.xyz.MessageService"/>
   

  如果需要用到该服务,如某个bean包含一个com.xyz.MessageService属性,则配置该bean如下所示

 

Xml代码 复制代码 收藏代码
  1. <bean id="referenceBean" class="com.nci.ReferenceBean">  
  2. <property name="messageService" ref="beanToPublish"/>  
  3. </bean>  
<bean id="referenceBean" class="com.nci.ReferenceBean">
<property name="messageService" ref="beanToPublish"/>
</bean>
 reference元素还有一些高级属性,详情请见spring dm reference。

看一下client的spring配置文件,这里用osgi:reference标签来引用服务,上面的配置中用osgi:service标签来发布服务

 

Xml代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"  
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd   
  5. http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">  
  6. <bean id="OSGiClient" class="osgi.example.client.Client">  
  7. <constructor-arg ref="ComputeService">  
  8. </constructor-arg>  
  9. </bean>  
  10. <osgi:reference id="ComputeService" interface="osgi.example.compute.Compute" cardinality="1..1">  
  11. </osgi:reference>  
  12. </beans>  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<bean id="OSGiClient" class="osgi.example.client.Client">
<constructor-arg ref="ComputeService">
</constructor-arg>
</bean>
<osgi:reference id="ComputeService" interface="osgi.example.compute.Compute" cardinality="1..1">
</osgi:reference>
</beans>
 从上面的示例,我们可以发现,服务的导出的时候都是基于接口的,服务的引用也是基于接口的,不过spring dm支持基于类的导出、导入,但是还是建议尽量基于接口,应该记住面向接口编程的思想,以应对将来有可能发生的改变。

 

 

3.5. 运行

 

由于add和multiply都是基于Compute接口对外导出服务,那么Client到底导入的是哪个服务呢?默认情况下,会导入启动较早的bundle服务(OSGi在bundle启动时,会为其分配一个ID值,启动越早,该值越小)。
运行之前,我们需要做这么一件事,搭建Spring-DM的运行环境:

(1)先到http://www.springsource.org/osgi上去下载Spring DM:spring-osgi-1.2.1-with-dependencies.zip, 解压后有dist和lib两个文件夹里有Spring DM运行的jar包。

(2)在 Package Explorer 上右击,然后点击Import --> Plug-in Development --> Plug-ins and Fragments,然后单击下一步,将弹出Import Plug-ins and Fragments 对话框,选择Directory,然后加到spring-osgi-1.2.1-with-dependencies.zip解压后的文件夹,并进入dist目录,然后点击next,将以下三个插件添加到你的“Plug-ins and Fragments to import”中:

 

以下是引用片段:
org.springframeork.osgi.bundle.core 
org.springframeork.osgi.bundle.extender 
org.springframeork.osgi.bundle.io

现在单击完成。Eclipse会将这三个套件导入到你的工作空间中,在那里你应能够在Package Explorer视图中看到它们。

(3)再将spring-osgi-1.2.1-with-dependencies.zip解压包里的lib目录下导入Plug-ins and Fragments to import,选择以下插件:

 

以下是引用片段:
org.springframeork.bundle.spring.aop 
org.springframeork.bundle.spring.beans 
org.springframeork.bundle.spring.context 
org.springframeork.bundle.spring.core 
org.springframeork.bundle.spring.jdbc 
org.springframeork.bundle.spring.tx 
org.springframeork.osgi.aopalliance.osgi

它们也加入到Package Explorer视图中。

(4)打开Run configurations,在OSGI Framework里新建一个运行平台,并将它名字改为springDM,选择四个我们写的bundles和上面导入的spring依赖bundles,然后点击Add Required Bundles,就可以添加入有依赖其它bundles而没有引入的bundle,最后点击Validate Bundles来最后确认依赖包加全了没有,提示No problems were dected.便可以运行了。

 

(5)运行之后,我们发现控制台输出结果:
The Sum is---11
通过ss命令,如下:
5 ACTIVE osgi.example.compute.multiply_1.0.0
6 ACTIVE osgi.example.compute.add_1.0.0
7 ACTIVE osgi.example.compute.client_1.0.0
将6停掉:stop 6
然后再refresh 7,控制台输出如下结果:
The Multiply is---30
通过 ss 命令,如下:
5 ACTIVE osgi.example.compute.multiply_1.0.0
6 RESOLVED osgi.example.compute.add_1.0.0
7 ACTIVE osgi.example.compute.client_1.0.0
现在multiply处于运行状态,而add已经被停止,所以client导入的服务实际是由multiply提供的。

 

 

 

 

4. 总结

 

通过该文档,我们已经清楚了,如何使用Spring DM导出、导入服务。Spring DM的一些高级特性请查阅spring dm reference。

分享到:
评论

相关推荐

    Spring与OSGI整合 计算器例子(转) +附整合代码和spring-osgi核心jar

    标题中的“Spring与OSGI整合 计算器例子(转) +附整合代码和spring-osgi核心jar”表明我们将探讨如何将Spring框架与OSGi(Open Services Gateway Initiative)模块化系统进行集成,并通过一个计算器的例子来说明这个...

    spring-dm-osgi整合jar包

    标题“spring-dm-osgi整合jar包”和描述“spring-dm整合osgi所需所有jar包”提及的核心知识点是Spring Dynamic Modules(简称Spring DM)与OSGi(Open Service Gateway Initiative)框架的集成。这两个技术在Java...

    OSGI整合Spring、Mybatis、Spring MVC实现一个登录应用案例

    在这个案例中,我们将探讨如何整合OSGI、Spring、Mybatis以及Spring MVC来实现一个登录应用。这个教程旨在帮助开发者理解如何在OSGI环境中集成这些流行的Java技术,以构建灵活且可扩展的应用程序。 首先,我们需要...

    RAP 整合 Spring (基于 Spring-osgi )

    标题 "RAP 整合 Spring(基于 Spring-osgi)" 暗示了本文将探讨如何在 RAP(Remote Application Platform)框架中集成 Spring 框架,并利用 Spring-osgi 进行服务管理和依赖注入。RAP 是一个用于构建富客户端应用...

    eclipse下构建spring与OSGI项目

    本教程将详细讲解如何在Eclipse环境中构建一个整合了Spring和OSGi的项目。 首先,我们需要了解Spring框架。Spring以其依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)的...

    OSGI应用中整合Spring、Mybatis、Spring MVC案例

    在OSGI(Open Service Gateway Initiative)应用环境中,整合Spring、Mybatis和Spring MVC可以实现模块化、可热更新和高效的企业级应用开发。OSGI是一个Java框架,它允许动态地安装、卸载和升级服务,提供了强大的...

    Eclipse RCP与Spring OSGi技术详解与最佳实践

    《Eclipse RCP与Spring OSGi:技术详解与最佳实践》由资源的Eclipse专家亲自...实战篇(第13-15章)详细讲解了Eclipse RCP与Spring OSGi框架、Hibernate ORM框架、JPA规范、Maven工具的整合,以及它与Java的模块化设计

    OSGISpring OSGISpring

    为了深入了解OSGI与Spring的整合,阅读"OSGI入门和整合Spring.pdf"文档将是十分有价值的。这份资源可能会涵盖以上提到的所有知识点,通过实例和最佳实践帮助开发者熟练掌握这两种强大的技术的结合。

    基于OSGi和Spring开发Web应用

    它放弃了传统的Java EE服务器标准,转而采用一套全新的基于OSGi内核的部署和打包系统,从而更加自然地整合了Spring编程模型。这种创新的架构不仅简化了应用服务器的配置和管理,同时也提升了应用的性能和稳定性。 #...

    Spring-OSGI 1.0 M3 中文手册

    对于企业级应用,Spring动态模块与OSGI平台的整合能提供以下功能: 模块内部更好的应用逻辑分离 同时部署同一模块的多个版本 在系统中动态发现和使用模块提供的服务 在系统运行时动态安装,更新和卸载模块 ...

    osgi spring实例

    然而,需要注意的是,Spring DM在Spring 3.0之后被弃用,取而代之的是Spring OSGi,所以这个实例可能较旧,或者需要更新到现代的Spring Boot与OSGi结合的方式。 至于压缩包内的"整合代码原版",这可能是一个完整的...

    OSGI入门和整合Spring

    将OSGI与Spring整合,可以充分利用两者的优点,构建更加灵活、可扩展且易于维护的系统。整合OSGI和Spring的主要目的是实现服务的动态发现和管理,以及在运行时动态装配和更新组件。 整合过程通常包括以下步骤: 1....

    OSGI资料,OSGI进阶,OSGI实战,OSGI入门和整合Spring

    本资料集合涵盖了OSGI的入门、进阶以及实战应用,特别是与Spring框架的整合。 《OSGI进阶》着重介绍了OSGI的核心概念和技术细节,包括: 1. **模块系统**:OSGI基于JAR文件作为模块的基本单位,每个模块都有自己的...

    Spring OSGi 入门.pdf

    Spring OSGi 与 Spring 框架的整合 - **Bean 容器**: Spring OSGi 使用 OSGi 服务作为 Spring Bean,实现服务的动态发现和依赖注入。 - **配置管理**: OSGi 服务注册表可以被 Spring 配置,允许 Spring 配置动态...

    学习SpringDM+OSGI的总结

    #### SpringDM+OSGI整合挑战 最后,我们来看看如何将SpringDM与OSGI结合使用,并解决其中遇到的一些问题。 1. **版本冲突**:在整合过程中,可能会遇到版本不兼容的问题。例如,SpringDM中的`org.springframework....

    基于osgi整合ssm框架注解开发

    总结,"基于osgi整合ssm框架注解开发"的主题涵盖了使用OSGi的模块化特性来管理和部署基于Spring、SpringMVC和MyBatis的Web应用,同时利用注解简化配置和开发过程。通过这样的整合,开发者可以构建出高度可扩展、模块...

    基于VirgoServer进行Spring Osgi Web开发

    在本文中,我们将深入探讨如何基于VirgoServer进行Spring Osgi Web开发,这是一个涉及OSGi容器、Spring框架和Web应用程序的集成技术。首先,我们需要确保拥有正确的开发环境和工具,包括Spring Tool Suite (STS),...

Global site tag (gtag.js) - Google Analytics