传统方式下,我们可以在bundle的activator(bundle启动时调用)中通过BundleContext.registerService()进行服务的注册,通过ServiceReferencesr = BundleContext.getServiceReference() 和BundleContext.getService(sr)两步得到服务。但这种方式有许多缺点:
1、 产生较多重复代码
2、 在启动时要实例化所有要发布的服务,影响启动时间
3、 有些注册的服务在运行期间不会被用到,额外占用内存
4、 增加了与OSGi框架的耦合
OSGI使用blueprint规范和声明式服务解决这些问题。
一、Blueprint:
1、服务发布
<bean id="timeService"class="com.star.test.TimeService">
<osgi:service id="osgiTimeService" ref="timeService" interface="com.star.test.ITimeService"/>
2、服务引用
<osgi:referenceid="osgiTimeService"interface="com.star.test.ITimeService"/>
Blueprint的实现方式是在服务引用的时候创建一个代理,在调用此服务时通过动态代理的方式调用。也就是说,即使服务的依赖还没有得到满足的情况下,也是可以发布服务的。而调用时,如果依赖的服务当前不可用,将会导致阻塞,直至依赖得到满足或超时。
Blueprint机制的一个好处在于能够应对在bundle更新期间服务取消和发布对框架的影响。除此之外,因为Blueprint方式使用了代理机制,因此服务必须要以接口的方式发布。
二、声明式服务
<?xmlversion="1.0" encoding="UTF-8"?>
//组建声明以及其中的一些属性
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"immediate="true" name="timeService.instance">//实现类
<implementationclass="com.star.test.timeService"/>
//接口声明<service>
<provideinterface="com.star.test.ITimeService"/>
</service>//依赖的服务,初始化服务时调用bind方法,服务停止时,调用unbind
<reference bind="initDataSource" cardinality="1..1"interface="com.star.test.IInitDataSourceService" name="initDataSource.instance"policy="dynamic" unbind="destroyDataSource"/>
<properties entry="OSGi-INF/db.properties"/>
</scr:component>
声明式服务是一种组件模型,它简化了组件的创建过程,这些组件会发布和使用OSGi服务。我们需要以声明的方式定义组件及其依赖,框架会基于依赖的满足情况来管理组件的生命周期。这意味着,只有组件的依赖完全满足的时候,才会处于激活(activated)状态,一旦依赖出现了缺失,组件就会处于停用(deactivated)状态。因此,声明式服务没有使用代理,但是能保证只要组件处于激活的状态,它的内部依赖就是已满足的。