应公司要求最近正在学习OSGI技术,以下是初学之后的一点总结
在接触OSGI之前,经常在网上接触到有关SOA的定义,出于时间有限在加上自己比较懒散,对这个名词的理解也只是停留在基本层面上,学习以后对SOA的实际应用上多少还是有了一定的了解。
OSGI是一种基于java平台的面向服务架构思想,在OSGI平台上部署应用,可在无需启动服务器的情况下动态改变系统的功能,类似于硬件的热插拔功能。
在传统的项目开发中,系统的所有模块都是部署到同一个Project中的,当一个系统比较庞大,涉及的模块较多时,该project下就会存在大量的package,时间一久,很难分辨package是属于哪一个模块的,简而言之,系统越庞大,结构越臃肿,为后期维护带来不便。
相比较传统开发方式,基于OSGI平台所开发的系统,每一个模块都是一个独立的plug-in工程,OSGI中称之为bundle,而系统主干则像是一个插台,根据需求可动态的将各种bundle以插线的方式插入插台,而不需要重启动服务器。这样设计使得模块之间的松耦合度变得更高,所开发的bundl还可以plug到别的系统中去来实现同样的服务。
既然是面向服务架构,系统bundle之间是如何发布、引用服务的呢?
在OSGI中,bundle之间的交互主要通过配置MANIFEST.MF文件来实现的,service的交互可以有两种方法实现:
一:通过实现BundleActivator接口---需要在MANIFEST.MF中指定Bundle-Activator配置
该接口主要定义了两个方法:
public void start(BundleContext context)---当bundle在系统中启动时执行
public void stop(BundleContext context)---当bundle在系统中停止时执行
两种方法都传入了BundleContext对象,可通过该对象来向系统服务注册表中注册服务
ServiceRegistration serviceReg=context.registerService(sercie标识, service instance, properties);
服务注册成功后返回ServiceRegistration对象,可调用其unregister()方法来移除已注册的服务
serviceReg.unregister();
引用服务同样通过BundleContext对象来完成
ServiceReference ref=bundleContext.getServiceReference(service标识);----service标识一般都是定义该service接口的完整类名
Object service=bundleContext.getService(ref);
获取到service后,便可调用其中的方法实现指定的功能
二:通过Declarative Services的方式实现---需要在MANIFEST.MF中指定Service-Component配置
此方式也是推荐使用的方式,通过DS 提升了Service发布和使用的简便性,可以很好的将Moudle分解为 Component+Service的模式
并且无需编写java代码,所有的配置通过xml文件即可实现
配置文件大致如下:
<?xml version="1.0" encoding="UTF-8"?>
<component name="ConfigFileValidator">
<!--Component的java实现类-->
<implementation class="org.riawork.demo.service.user.impl.ConfigFileValidatorImpl"/>
<!--对外提供的服务-->
<service>
<provide interface="org.riawork.demo.service.user.Validator"/>
</service>
<!--引用外部的服务-->
<reference name="HttpService"
interface="org.osgi.service.http.HttpService" //定义服务的借口
bind="setHttpService" //绑定服务后调用的方法
unbind="unsetHttpService" //解绑后调用的方法
policy="dynamic" //引用服务的策略
cardinality=”1..1”
/>
</component>
注:在引用策略的定义上可有两种方式static(默认)、dynamic
若设置成static,一旦引用的服务发生变动整个Compont便会重启
设置成dynamic,服务发生变动只是调用其中的bind和unbind方法
cardinality的值主要是0,1,n三个数的组合:
0..1 最多只引用其中的一个服务,即bind方法只执行1此,但系统也可以不存在可用的服务
0..n 可引用0或n个服务,这种情况下bind方法会执行多次,每存在一个可用的服务便执行一次bind方法
1..1 最多只引用其中的一个服务,且系统中必须存在一个可用的服务(默认)
1..n 引用的服务必须存在,可使用多个服务
如果系统中存在多个可引用的服务,但cardinality规定至多引用一个服务,这种情况下:
一旦component所引用的服务stop,该component首先执行的并不是其unbind方法,而是继续寻找新的可用服务调用其bind方法进行绑定
然后才会调用其unbind方法对之前引用的服务进行解绑.