- 浏览: 1650085 次
- 性别:
文章分类
- 全部博客 (2929)
- 非技术 (18)
- Eclipse (11)
- JAVA (31)
- 正则表达式 (0)
- J2EE (4)
- DOS命令 (2)
- WEB前端 (52)
- JavaScript (69)
- 数据库 (8)
- 设计模式 (0)
- JFreechart (1)
- 操作系统 (1)
- 互联网 (10)
- EasyMock (1)
- jQuery (5)
- Struts2 (12)
- Spring (24)
- 浏览器 (16)
- OGNL (1)
- WebService (12)
- OSGi (14)
- 软件 (10)
- Tomcat (2)
- Ext (3)
- SiteMesh (2)
- 开源软件 (2)
- Hibernate (2)
- Quartz (6)
- iBatis (2)
最新评论
OSGi中获取Service的几种方式
在OSGi中,Service是动态管理的,OSGi容器提供的好几种获取和使用Service的方式,那么这几种方式各有什么优、缺点
呢,下面我们就以org.osgi.service.log.LogService为例来分别讲一讲。
一。最原始的方式:
2 ServiceReferenceref = context.getServiceReference(LogService. class .getName());
3 if (ref != null ){
4 // 获取Service实例
5 LogServiceservice = (LogService)context.getService(ref);
6 if (service != null ){
7 // 调用Service方法
8 service.log(LogService.LOG_INFO, " ok " );
9 // 释放Service,在此之后不应该再继续使用Service实例
10 context.ungetService(ref);
11 }
12 }
优点:很难说有什么优点,硬要说几句的话,那就是逻辑够简单,调用最少,适合一次性操作。
缺点:需要判断返回值是否为null,需要手动申请和释放service,由于OSGi的动态性,请在获取ref后尽快使用,无法保证ref长期有效。每
次访问都会有service获取和释放的开销。
用途:适合于不频繁的调用service,且在service不可用时也能继续执行后续操作的场景。
二。使用ServiceListener:
在Service注册时访问:
2 public void serviceChanged(ServiceEventevent){
3 switch (event.getType()){
4 case ServiceEvent.REGISTERED:
5 // 获取Service引用
6 ServiceReferenceref = event.getServiceReference();
7 // 获取Service实例
8 LogServiceservice = (LogService)context.getService(ref);
9 if (service != null ){
10 // 调用Service方法
11 service.log(LogService.LOG_INFO, " ok " );
12 // 释放Service,在此之后不应该再继续使用Service实例
13 context.ungetService(ref);
14 }
15 break ;
16 case ServiceEvent.UNREGISTERING:
17
18 break ;
19 }
20
21 }
22 }, " (objectclass=org.osgi.service.log.LogService) " );
独立于ServiceListener的访问:类似于方式一,在Listener中获取service并且保存到成员变量中,以供后续访问:
2 public void serviceChanged(ServiceEventevent){
3 switch (event.getType()){
4 case ServiceEvent.REGISTERED:
5 if (ref == null ){
6 ref = event.getServiceReference();
7 service = (LogService)context.getService(ref);// 保存实例以备后续访问
8 }
9 break ;
10 case ServiceEvent.UNREGISTERING:
11 if (ref == event.getServiceReference()){
12 context.ungetService(ref); //释放实例
13 service = null ;
14 ref = null ;
15 }
16 break ;
17 }
18
19 }
20 }, " (objectclass=org.osgi.service.log.LogService) " );
访问Service:
优点:只在Service变更时产生一次service获取开销,动态感知service的注册和注销。
缺点:在ServiceListener注册之前已经存在的Service无法监听到。需要自己维护service的获取和释放。在需要监听多个
Service实例时,使用并不方便。
三、使用ServiceTracker
ServiceTracker其实是对ServiceListener实现方式的封装,使得对service的获取更加简洁,同时也解决了不能监听到已经
存在的Service的问题(其实就是在增加ServiceListener的同时调用
BundleContext.getAllServiceReferences方法以获取现有的Service引用)。
使用ServiceTracker使得获取Service的代码更加简洁和一致,不必再考虑Service是否存在的问题,并且
ServiceTracker也提供了更加有效的监听Service的方式。
一次性访问:
2 tracker.open();
3 LogServiceservice = (LogService)tracker.getService();
4 if (service != null )service.log(LogService.LOG_INFO, " ok " );
5 // 获取多个Service
6 Object[]services = tracker.getServices();
7 // 获取Service的数量
8 int count = tracker.getTrackingCount();
9 tracker.close();
在Service注册和注销时访问:
2 @Override
3 public ObjectaddingService(ServiceReferencereference){
4 LogServiceservice = (LogService) super .addingService(reference);
5 if (service != null )service.log(LogService.LOG_INFO, " ok " );
6 return service;
7 }
8
9 @Override
10 public void removedService(ServiceReferencereference,Objectservice){
11 ((LogService)service).log(LogService.LOG_INFO, " removedService " );
12 super .removedService(reference,service);
13 }
14 };
15 tracker.open();
16
17 // 在自身lifecycle结束时关闭tracker
18 tracker.close();
有一点需要注意的是,tracker需要调用open方法才能监听到Service,另外,在bundle
stop以后,bundle内open的ServiceTracker不会自动关闭,所以一定不要忘记在bundle结束之前,关闭所有在bundle中
open的ServiceTracker。
四、使用Declarative Services
在OSGi 4以后的规范中,增加了Declarative Services方式。Declarative Services
是一个面向服务的组件模型,它制订的目的是更方便地在 OSGi
服务平台上发布、查找、绑定服务,对服务进行动态管理,如监控服务状态以及解决服务之间的复杂的依赖关系等问题。Declarative
Services 采用服务组件的延迟加载以及组件生命周期管理的方式来控制对于内存的占用以及启动的快速,很好的解决了传统的 OSGi
服务模型在开发和部署比较复杂应用时内存占用大、启动慢等问题,并且对服务组件的描述采用XML来实现,十分便于用户理解和使用。
在equinox-SDK-3.6M5开发包中,包含了一个DS的实
现:org.eclipse.equinox.ds_1.2.0.v20100125.jar,将这个jar和一个依赖的
jar:org.eclipse.equinox.util_1.0.100.v20090520-1800.jar部署到OSGi容器中,就可以使用
DS服务了。equinox中DS服务的实现,是综合使用了BundleListener,ServiceListener等相关OSGi
API,将大量繁杂和冗长的代码细节藏在了实现背后,开发者只需要了解简单的xml语法和配置方式即可方便的使用。
要使用DS,一般有以下几个步骤:
1.定义Component实现类:
2
3 import org.osgi.service.component.ComponentContext;
4 import org.osgi.service.log.LogService;
5
6 public class TestComponent{
7 public void activate(ComponentContextcontext){
8 System.out.println( " activate( " + context + " ) " );
9 }
10
11 public void deactivate(ComponentContextcontext){
12 System.out.println( " deactivate( " + context + " ) " );
13 }
14
15 public void modified(ComponentContextcontext){
16 System.out.println( " modified( " + context + " ) " );
17 }
18
19 public void bind(LogServiceservice){
20 service.log(LogService.LOG_INFO, " bind " );
21 }
22
23 public void unbind(LogServiceservice){
24 service.log(LogService.LOG_INFO, " unbind " );
25 }
26 }
2.编写component.xml:
2 < scr:component xmlns:scr ="http://www.osgi.org/xmlns/scr/v1.1.0"
3 activate ="activate" deactivate ="deactivate" modified ="modified" name ="test"
4 xsi:schemaLocation ="http://www.osgi.org/xmlns/scr/v1.1.0http://www.osgi.org/xmlns/scr/v1.1.0" >
5 < implementation class ="org.dbstar.osgi.dstest.TestComponent" />
6 < reference bind ="bind" cardinality ="1..1"
7 interface ="org.osgi.service.log.LogService" name ="LogService"
8 policy ="dynamic" unbind ="unbind" />
9 </ scr:component >
以上是有namespace的xml写法,在equinox中也支持没有namespace的写法,Eclipse中有相应的插件来提供图形化的界面来维 护component xml。以下是没有namespace的xml写法:
2 < component name ="test" >
5 < implementation class ="org.dbstar.osgi.dstest.TestComponent" />
6 < reference bind ="bind" cardinality ="1..1"
7 interface ="org.osgi.service.log.LogService" name ="LogService"
8 policy ="dynamic" unbind ="unbind" />
9 </ component >
3.将写好的xml放置到bundle根目录下的OSGI-INF下面
4.在bundle的描述文件META-INF/MANIFEST.MF中增加component相关的header:
注意xml的文件名不是绝对的,放置的目录也不是绝对的,只要在Service-Component中包含正确的路径就可以了。
一个bundle可以注册多个component,只要编写多个xml文件即可,在Service-Component中以逗号分隔。
Component的注册并不依赖Activator,所以bundle的Activator不是必须的。
另外在我的使用过程中,发现一个问题,如果xml中没有使用namespace,那么component节点上的几个callback类属性都不能定义,
例如activate属性。如果使用了namespace,那么这些属性都是可以正常使用的,不知道这算不算是bug。
关于DS规范的详细内容,可以参见:OSGi 中的 Declarative Services 规范简介
最后总结一下,综上所述的四种获取service的方法,使得service的获取越来越简单,开发者只需关注自己的逻辑,而不必纠缠于OSGi繁琐的
Service Lookup中去,同时还提供了更加方便使用的API,大家可以根据自己的需要,选择最合适的使用方式。
相关推荐
在实际应用中,OSGI服务DS事件的使用常常涉及以下几个关键概念: 1. `Component`: 组件是OSGI的基本单元,它可以提供服务,也可以使用服务。 2. `Service Reference`: 服务引用是组件获取服务的途径,它包含了服务的...
在非OSGi环境中,Spring事务管理通常通过以下几种方式实现: 1. **编程式事务管理**:在业务代码中手动调用`TransactionTemplate`或`PlatformTransactionManager`进行事务的开始、提交、回滚操作。 2. **声明式事务...
标题中的“OSGi Hibernate”指的是将Java的OSGi(Open Service Gateway Initiative)框架与Hibernate ORM(Object-Relational Mapping)工具进行集成的技术实践。OSGi是一种模块化系统,它允许在运行时动态地发现、...
OSGi(Open Service Gateway Initiative)是一种用于Java平台的模块化规范,旨在使开发人员能够构建可管理和维护的大型应用程序。OSGi允许单个应用程序由多个模块组成,这些模块可以独立地安装、启动、停止、更新和...
OSGi是一种模块化系统,它允许Java应用程序以模块化的方式进行构建,提供了动态服务发现和依赖管理的能力。而Servlet容器,如Tomcat、Jetty等,是用于运行Web应用的地方,它们处理HTTP请求并调用相应的Servlet来响应...
"OSGi.NET-master.zip_c#osgi_osgi_osgi.net github_模块化" 这个标题揭示了几个关键信息。首先,它提到了“OSGi.NET”,这是一个专门为.NET平台实现的OSGi(Open Service Gateway Initiative)框架。OSGi是一个Java...
OSGi的核心在于其模块系统,称为服务组件运行时(Service Component Runtime,SCR),它定义了一种将Java类打包成称为“bundle”的模块化单元的方式。 OSGi的优势主要体现在以下几个方面: 1. **模块化**:OSGi...
OSGI(Open Services Gateway Initiative)是一种模块化系统和Java服务框架,它允许开发人员将应用程序分解为一组可独立更新和管理的小型模块。在OSGI环境中,服务是模块之间通信的关键机制。本主题将深入探讨OSGI的...
OSGi(Open Service Gateway Initiative)是一种模块化系统和Java服务框架,它允许开发人员将应用程序分解为一组可独立更新和管理的小型、自包含组件,称为“bundles”。这些bundle之间可以通过服务接口进行交互,...
OSGi(Open Services Gateway Initiative)是一种开放标准,用于创建模块化和可动态更新的应用程序和服务。在《OSGi实战》中,"用户验证"这一章节着重讲解了如何在OSGi环境中实现安全的用户身份验证机制。这篇博文...
OSGi,全称为Open Service Gateway Initiative,是一种Java平台上的动态模块系统,旨在为软件开发者提供模块化、可扩展且动态的开发环境。OSGi的核心理念是通过定义一套标准的模块化框架,使得Java应用程序能够根据...
Spring-DM (Spring Dynamic Modules 或 Spring OSGi) 是一种用于将Spring框架整合到OSGi环境的技术。这种结合使得开发者能够利用Spring的依赖注入和管理功能来构建更加灵活、可扩展的应用程序。以下是Spring-DM的...
基于Equinox平台的OSGi Bundle开发提供了一种强大且灵活的方式来构建复杂的、可扩展的Java应用程序。通过利用OSGi的服务模型和动态模块化特性,开发人员可以创建出高度解耦、易于维护和升级的系统。无论是构建企业级...
OSGi(Open Service Gateway Initiative)是一种模块化系统和服务组件模型,它允许开发人员构建、部署和管理复杂的应用程序和服务。OSGi最初是为了电信行业的网关设备而设计的,但后来被广泛应用于企业级Java应用的...
在Eclipse中配置一个基于Eclipse Equinox OSGi的Web应用程序涉及到以下几个关键知识点: 1. **OSGI基础概念**:OSGI的核心是bundle,每个bundle都是一个独立的Java模块,包含类、资源和元数据。它们通过导出和导入...
书中的源码提供了丰富的实例,帮助读者理解并实践模块化模式和OSGi(Open Service Gateway Initiative)框架的应用。源码的上传是为了克服原存储在Google上的访问难题,现在在CSDN平台上可以方便地获取。 模块化...
`Bundle`接口定义了几种不同的状态,这些状态反映了`Bundle`在其生命周期中的不同阶段: - **UNINSTALLED**(未安装状态):`Bundle`尚未安装到框架中。 - **INSTALLED**(已安装状态):`Bundle`已经安装到框架中...