网站地图
  
  高级搜索
  首页   技术论坛   博客 派计划   产品中心   资源中心   银弹在线   商城  





Eclipse Equinox OSGI Declarative Service 实现分析    
#1楼
给作者发送短消息 给作者发送短消息 实名会员 
查看用户其他信息
总分 7739 分
财富 6596 goCom币
威望 8229
排名 第 2 名
段位 新手必读
Equinox项目是Eclipse开源组织提供的OSGi框架的实现。Equinox 的org.eclipse.equinox.ds项目提供了OSGi R4规范中的Declarative Service标准服务的实现。Declarative Service提供了基于OSGI平台之上的面向服务构件模型(Service-Oriented Component Model),也为在OSGI基础之上搭建SOA应用提供了可能。
背景信息
Equinox项目是Eclipse开源组织提供的OSGi框架的实现。Eclipse自3.0版本开始,其内核移植到OSGi框架上。通过OSGi框架强大的组件控制,交互和管理能力,再加上Eclipse插件的自有特点,Eclipse开源框架得到了跳跃式的发展。同时,OSGi规范得益于Eclipse IDE环境庞大的使用者,OSGi联盟也进入了快速发展时期。
 
Equinox项目概述
Equinox项目包括OSGi R4版本规范核心框架的实现,一系列OSGi标准服务Bundle及运行基于OSGi的系统的一些基础构件。目前,Equinox项目包括OSGi核心框架的实现,OSGi标准服务Bundle实现,OSGi的服务器端(J2EE实现)应用,Equinox部署更新框架及一些研究方向(未成熟发布的构想如JMX管理,安全管理,面向方面的设计与应用等)。
 
Equinox Declarative Services(DS)
Equinox 的org.eclipse.equinox.ds项目提供了OSGi R4规范中的Declarative Service标准服务的实现,该组件由Prosyst公司提供实现。Declarative Service提供了基于OSGI平台之上的面向服务构件模型(Service-Oriented Component Model),也为在OSGI基础之上搭建SOA应用提供了可能。Declarative Service实现并没有包含在Eclipse的默认软件包中,需要从Eclipse的CVS中获取。代码位于:pserver:anonymous:dev.eclipse.org/cvsroot/eclipse路径下。
 
       Equinox在没有DS实现之前,对于服务的注册需要手工来做,如下面的代码:
service = new HelloServiceImpl();
 
// register the service
context.registerService(HelloService.class.getName(), service, new Hashtable());
 
// create a tracker and track the service
helloServiceTracker = new ServiceTracker(context, HelloService.class.getName(), null);
helloServiceTracker.open();
 
// grab the service
service = (HelloService) helloServiceTracker.getService();
service.speak();
 
       在提供了DS之后可以采用XML文件的方式来声明:
<?xml version="1.0" encoding="UTF-8"?>
<component name="HelloService">
    <implementation class="com.primeton.osgi.HelloServiceImpl"/>
    <service>
       <provide inter/>
    </service>
</component>
上面的XML文件声明了HelloService的构件,实现类是com.primeton.osgi.HelloServiceImpl,同时,声明了构件的服务接口为com.primeton.osgi.HelloService。如果不声明服务,当你使用类似下面的代码是查找不到服务的:
ServiceReference reference = context.getServiceReference(TestService.class.getName());
TestService service = (TestService)context.getService(reference);
service.test();
调用BundleContextgetServiceReference方法将返回空。
 
    类似于SCA规范的构件装配模型,Component可以引用别的Component的服务。如我们声明一个TestServiceTestService引用了HelloService
<?xml version="1.0" encoding="UTF-8"?>
<component name="TestService">
    <implementation class="com.primeton.osgi.TestServiceImpl"/>
    <reference name="HelloService" inter bind="setHelloService" unbind="unsetHelloService" policy="dynamic"/>
    <service>
       <provide inter/>
    </service>
</component>
是不是和SCA的装配模型描述文件有点相似呢?^_^
 
下面对Equinox的Declarative Service的实现进行一下分析。
 
加载ComponentDescriptor
首先,构件的描述文件是如何被加载的呢?加载由org.eclipse.equinox.ds.tracker.BundleTracker来实现。BundleTracker会遍历所有的Bundle处于ACTIVE状态的Bundle,BundleTracker回调BundleTrackerCustomizeraddingBundle方法,读取所有的ComponentDescriptor,并加入到异步工作队列WorkQueue中。
 
Resovle ComponentDescriptor
加入到异步队列中的ComponentDescriptor需要由org.eclipse.equinox.ds.resolver. Resolver进行解析,判断Component所依赖的服务构件是否都存在,并满足条件。然后创建ComponentConfiguration
 
解析Manifest Header
org.eclipse.equinox.ds.parser.Parser会解析Manifest文件,读取Manifest文件中的Service-Component属性。代码如下:
    private ManifestElement[] parseManifestHeader(Bundle bundle) {
 
       Dictionary headers = bundle.getHeaders();
       String files = (String) headers.get(ComponentConstants.SERVICE_COMPONENT);
 
       try {
           return ManifestElement.parseHeader(ComponentConstants.SERVICE_COMPONENT, files);
       } catch (BundleException e) {
           Log.log(1, "[SCR] Error attempting parse Manifest Element Header. ", e);
           returnnew ManifestElement[0];
       }
    }
 
 
因此,为了使Component的描述文件被加载,必须在Manifest文件中申明要加载的xml文件。如下所示:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Test Plug-in
Bundle-SymbolicName: test
Bundle-Version: 1.0.0
Service-Componen: test.xml
Import-Package: org.osgi.framework;version="1.3.0",
 org.osgi.util.tracker;version="1.3.1"
Eclipse-LazyStart: true
 
 
解析ComponentDescriptor
org.eclipse.equinox.ds.parser.Parser同时会负责解析构件描述文件。
 
创建Component实例
org.eclipse.equinox.ds.instance.BuildDispose负责根据ComponentDescriptor创建Component的实例。具体参见buildComponentConfigInstance方法。
ComponentDescription componentDescription = componentConfiguration.getComponentDescription();
 
Object instance = createInstance(componentDescription);
 
componentInstance = instantiate(componentConfiguration, instance);
 
createComponentContext(usingBundle, componentInstance);
 
bind(componentInstance);
 
activate(componentInstance);
 
componentConfiguration.addInstance(componentInstance);
1.       首先从ComponentConfiguration中获取ComponentDescriptor.
2.       根据ComponentDescritptor创建一个Component的实例。
3.       创建Component的上下文ComponentContext。
4.       将Component需要的Service进行绑定。
5.       调用Component的activate方法,激活Component。
 
Component可以是任何一个Java类,而不需要继承或实现OSGI的类或接口,但可以定义一个activate方法,在Component被激活时作相关处理。
 
org.eclipse.equinox.ds.instance.InvokeMethod负责在调用Component的相关方法,采用类反射的机制将Server绑定到Component上。InvokeMethodfindBindOrUnbindMethod会在Component的实现类和超类中去查找绑定方法。
 
从以上分析,可以看出EquinoxDeclarative Service实现了一个服务构件定义、加载、装配、服务查找的一个服务构件运行环境。和SCA的构件装配模型异曲同工。Declarative Service规范应该早于SCA规范的制定,因此,在某种程度上,SCA装配模型参考了Declarative Service的服务构件模型,并在此基础上发展完善,多出了ContributionComposite等概念,对于服务绑定的范畴也进行了拓宽,并不局限于Java语言的Service,从而做到了语言无关、平台无关。
 
 

Re: Eclipse Equinox OSGI Declarative Service 实现分析    
#2楼
给作者发送短消息 给作者发送短消息  
查看用户其他信息
初级会员
 

Re: Eclipse Equinox OSGI Declarative Service 实现分析    
#3楼
给作者发送短消息 给作者发送短消息 实名会员 
查看用户其他信息
总分 1899 分
财富 1524 goCom币
威望 2060
排名 第 15 名
段位 新手必读
 

Re: Eclipse Equinox OSGI Declarative Service 实现分析    
#4楼
给作者发送短消息 给作者发送短消息 实名会员 
查看用户其他信息
总分 127 分
财富 135 goCom币
威望 123
排名 :(
段位 新手必读
 




发表回复
账号用户名   密码   登录
内容:url email imgsrc image code quote
范例 Example
bold italic underline linethrough   


 [更多...]