转自:http://blog.csdn.net/songliwei2005/archive/2008/07/17/2664033.aspx
一、Eclispe 插件体系结构概述
Eclispe 是世界上最大的开源组织的产品,是一个基于Java 的可扩展的开发平台,就其本身来说,它只是一个框架和一组服务,用于通过组件构建开发环境。
Eclipse 是一个全能的工作平台,主要得益于其插件体系结构。整个Eclipse 采用平台加插件体系结构,Eclipse Platform Runtime 作为整个系统的基础,是一个专门为插件提供的运行时容器,其本身不具备任何面向用户的业务功能。就像一个常见的J2EE 容器,如果没有应用,那么也就是一个纯粹的中间件。同样如果没有插件,Eclipse 平台的运行时就是一个纯粹的容器。所有的业务功能,都是封装在Eclipse 的插件中中的Workspace ,Team ,JDT (Java 开发工具包)和PDE (插件开发环境)本身就 是用插件来实现的。 Eclipse 系统架构图如下。
由于Eclipse 采用了完全开放的扩展方式,在熟练的程序员手里,Eclipse 更像一个高级的玩具,你可以自由实现你想要的功能,唯一的束缚可能就是你的想象力了。Eclipse 的给我们带来最重要的思想就是微内核与可扩展的插件体系结构。与Eclipse 几乎同时代崛起的JBoss 采用的也是微内核的可扩展机制,JBoss 的流行带来的JMX 的流行,JMX 规范使得基于Java 的应用框架或中间件平台常常会采用这种流行的可扩展方式。但是JMX 本身作为一个规范,其过高的抽象程度虽然带来了更多的灵活性,但是降低了开发时的效率,对于诸如应用服务器这样的中间件虽然适用,但是对于Eclipse 这样面向应用的中间件(或者说是面向插件),JMX 的级别显得有些原始。而Eclipse 的插件机制更为彻底,也更为具体,因此在特定的平台上,具有更方便的使用性。当应用服务器发展风头正劲的21 世纪初期,Eclipse 的出现无疑让人们对中间件的看法更加深化。Eclipse 被设计成一个中间件服务器,每一个插件就是一个运行在Eclipse 规范上的应用包,中间件并不会为你提供服务,而真正的业务
工作都是运行在中间件中的业务模块。它将这种插件模式发挥到了极至。Eclipse
内核只是一个纯粹的插件运行环境,而我们常常看到的Eclipse 各项功能,其实都是体现在那些林林总总的Eclipse 插件中的。
为 什么水平的分层机构和微内核可扩展的机制会成为如此受欢迎的流行因素呢?计算机界的一位泰斗曾经解释说“增加一个中间层可以解决软件中的大部分问题”。垂 直的体系结构具有比较弱的可扩展能力,对于开发,测试等等都会带来发散的结果。在面向对象的软件世界里,适当的层次结构就成为我们降低耦合,增加扩展性的 有力工具。其实插件的结构在软件行业中并不是一个很新的概念,早期的计算机系统,软件硬件是一体的,那时候的应用软件是固化在硬件中的逻辑,随着操作系统 和编译程序的发展,软件,硬件的体系结构才相对独立,而应用软件和硬件之间的平台就是操作系统。此时,各种应用程序就是运行在操作系统之上的插件,操作系 统就是一个插件平台。而现代的中间件和Eclipse 这样的平台不过是操作系统之上的另外一种插件容器。
从Eclipse3.0 以后,Eclipse 就采用OSGI 来作为其插件体系结构实现的基础。OSGI 是一套开放的标准,Eclipse 引入OSGI 主要是考虑网络范围内的互操作性。每个Eclipse 的插件都是一个OSGI 的模块,Eclipse 的平台核心就是一个OSGI 的参考实现。在最近的版本中,OSGI 的参考实现已经从内核中被剥离,形成了一个新的子项目:Equinox-an OSGi framework 。一个OSGI 模块最重要的就是Bundle 和Service ,我们可以认为Bundle 是一种插件管理器,主要是通过BundleActivator 管理模块的生命周期,而Service 则是这个模块可暴露对外的服务对象。这里体现了OSGI 和传统的Plug-in Framework 不同的一个地方,管理和静态结构分开,每个Bundle 拥有自己的ClassLoader 以及context ,通过context 可进行服务的注册、卸载等,这些操作都会通过事件机制广播给相应的其他的Bundle ;一般来说都为通过在Bundle 中编写初始需要注册的服务的方法来完成Bundle 可供外部使用的服务的暴露功能。
启动时Eclipse 核心会检查所有的插件并注册,但是直到被调用,该插件的才会被实例化,这也就是我们常说的懒加载。Eclipse 启动后,插件处于等待激活和被调用状态,由程序激活插件的功能,或用户输入会造成插件的初始化的事件等,从而实现预定的功能,这一点和一般的应用程序开发本质上没有区别,只不过以前我们开发应用程序,完全是Case by case , 也就是各为其主,现在如果你决定投身到Eclipse 的世界中,你就要树立这样一种世界观,即所有的功能都是通过插件来实现的,你的应用程序不过是Eclipse 平台运行时和你的插件的集合。
在Eclipse 中 有一个契约以保证插件能够和插件的容器通信,既拥有一个完整的插件开发和配置规范。这里首先需要一个抽象的插件定义,基础平台只通过固定的抽象接口和具体 的插件交互,在平台的眼里,是不应该知道不同的插件的差别的。平台和插件(包括插件与插件通过平台的)的交互通过固定的接口实现,而用户与插件的交互则是 通过插件本身对UI 事件的响应来实现的。扩展(Extension )是Eclipse 中一个关键的机制,插件利用扩展向Eclipse 平台添加新功能。但是扩展不能随意地创建,必须按照扩展点(Extension Point ,参照图一中插头的标记)定义的规范进行明确的声明,Eclipse 才能识别出这些扩展。所谓扩展点,就是Eclipse 定义出来可以让你扩展的地方,可以认为是一些扩展的契约; 而扩展,这是你对这些扩展点的实现,当然你自己的插件也可以定义扩展点供别的开发人员扩展。我们不仅可以使用Eclipse 提供的众多现成的扩展点,而且还可以定义新的扩展点,并在该扩展点上进行扩展。Eclipse 平台本身的实现定义了很多的扩展点供你扩展,你可以从多个角度进行扩展,常见的扩展点有:
◆ 动作集(actionSet );
◆ 编辑器(editor );
◆ 弹出式菜单(popUpMenu );
◆ 视图(views );
◆ 透视图(perspectives );
◆ 属性页(propertyPages) 等。
你可以认为一个扩展点就是不同的插件和Eclipse 平台绑定的契约,而扩展则可以认为是一个具体的绑定,一个扩展点会有多个扩展。举个例子,Eclipse 提 供了一个视图的扩展点,因此我们平台的很多视图都是对该扩展点的扩展,那么如果你的插件扩展了视图扩展点,那么系统就会明确的知道你一定有一个视图,并且 该视图要实现特定的接口,以保证平台能够加载并显示它,但是视图本身的逻辑和要展现的内容,平台则不会关心。这也反映了一种互操作的通用设计原则,即规范 化的接口和配置。举个简单的例子,EJB 容器和EJB 本身的交互,很多时候就要通过EJB 规范的接口及事务,安全等的配置来实现,这种接口和配置的规范越简单,其灵活性越好但是开发的代价越高。因此在现实中需要某种平衡。比如,Servlet 只定义了简单的DOGET 和DOPOS 这样的接口,虽然简单灵活,但是开发成本则随之增加,所以有了JSP 这样复杂一些的规范,但是可以简化开发。在JSP 的基础上,我们很快又有了Struts 等这样的框架,复杂程度更上一层,但是开发的效率则又有提高。Eclipse 通过大量的插件和扩展点很好地实现了这种平衡,一旦掌握了这种开发技巧和思维方式,基于Eclipse 项目本身的优秀插件和无数的开源插件,你的开发效率将得到很大的提高。
那么我们的插件应该如何来组织和编写呢? Eclipse 的平台价值就在于他已经准备好了被扩展,因此提供了完整的插件开发环境,也就是我们常说的PDE 。事实上,开发Eclipse 程序的核心任务主要包含创建实现一个或者多个扩展的插件。我们看见很多的平台因为没有一个易用的开发工具而淹没在茫茫的代码中,幸亏Eclipse 提供了一个非常好用的插件开发环境(P D E )。P D E 是作为Eclipse SDK 的一个部分而存在的,它本身的实现也是通过一组插件来实现的。如果你需要创建一个插件,你就必须打开PDE 透视图,为你的插件新建一个Plug-in 项目。插件项目具有一些特定的配置,比如说它们每一个都有一个插件描述符(一个manifest 和/ 或一个plugin.xml 文件),一个基于描述符指定的依赖关系的动态classpath ,特殊的编译器,和其他配置属性。PDE 提供了一个插件创建向导,可以选择各种需要的部分创建插件项目。从开发人员的直觉来看,所谓的插件就是一些符合接口的类的集合和一些配置文件定义交互的关系。我们当然可以手写配置文件,但是使用PDE 的可视化编辑器工作起来效率更高。插件Manifest 编辑器用到3 个文件:MANIFEST.MF ,plugin.xml 和build.properties. 它允许你编辑所有必要的属性来描述一个插件,它的基本运行时要求,依赖,扩展,扩展点等等,当开发插件的时候你需要做更详细的了解。
由于Eclipse 的兴起,直接给Java IDE 市场带来深远的影响,基于完全开源的Eclipse Java IDE ,一些商业公司发布自己IDE 产品(如WSAD ,MyEclipse ,RAD 以及国内一些厂商的IDE 等)。目前的JavaIDE 领域,Eclipse 占据绝对优势,今年2 月份连著名的开发工具厂商Borland 都宣布要出售开发工具部门,未来的JBuilder 将怎样,还是一个未知之数。与此同时,Eclipse 的发展直接带动了第三方插件市场的发展。管国外有很多著名的开源Eclipse 插件,但一些商业性质的插件也在新兴的市场上站住了脚。对国内的软件公司,这未尝不是一个好机会,比如国内的中创软件,就正在从事这方面的一些工作。尽管中国的插件市场还有很多困难需要克服,但是我们期待国内的软件公司能在Eclipse 插件领域有所成就。
二、基于Eclipse RCP 的应用开发
Eclipse Rich Client Platform (RCP) 是基于Eclipse 项 目的一个开发富客户端应用程序的框架,旨在提供一种快速开发的,功能强大的,可扩展的应用平台。在需求变化异常频繁的今天,企业级的客户端应用程序必须具 有组件化,跨平台,本地观感,可伸缩性强,方便更新等特性。如果开发团队从头开始开发一个企业级的客户端应用,那么他们需要具有优秀的开发技术和丰富的开 发经验来设计并实现所有这些特性,但是并不是所有的开发团队都具有这样的能力。幸运的是Eclipse RCP 提供了一个满足所有这些特性的基础平台,Eclipse RCP 基于Eclipse 的插件体系构架使开发团队可以很快的基于这个平台开发自己的客户端应用,在开发过程中,开发团队只需要集中考虑如何用Eclipse 插件机制实现业务逻辑。
Eclipse RCP 是Eclipse Platform 的一个子集(如图),
从Eclipse3.0 版本开始,Eclipse 项目组对代码进行了重构,将IDE 与Workbench (工作台)彻底分离,实现了一个Generic Workbench ,使得RCP 应用中不再有IDE 的影子。而其它的可选部件及丰富的插件集更是让RCP 应用在各个领域都可以大展拳脚。
Eclipse RCP 主要有以下几个优点:
1. 组件化(UI ,Update ,Help )
Eclipse RCP 基于Eclipse 特有的插件体系构架,每一个业务模块都设计为一个可方便重用的插件,把业务模块之间的访问转化为插件之间的相互访问,这样就实现了模块之间的解耦,以达到软件PnP (插件的即插即用)的目的。
2. 跨平台
跨平台是RCP 的基础要求之一。只要不在客户端应用中包含OS 特有的功能,基于RCP 开发的所有客户端应用都是能够跨平台的。
3. 本地观感
Eclipse 中的图形包SWT 而不是JDK 中自带的AWT/Swing 包, SWT 在显示用户界面时使用的是本地OS 本地用户界面代码,所以呈现出来的用户界面样式就是本地OS 特有的界面样式。
4. 可扩展性强
基于OSGi 及插件体系结构的内核为应用程序提供了一个安全,稳定的运行时环境,扩展点的思想更是使得用户可以方便地搭建各种类型、用途的应用程序以及该应用程序特有的扩展点。可以说,Eclispe RCP 就是设计用来被扩展的。
5. 强大的开发工具支持和完善的本地帮助文档
随着Eclipse 的插件开发环境(PDE )的日趋成熟,使得基于RCP 的插件开发越来越方便,加速了产品的研发进程。在Eclipse 的帮助系统可以找到与Eclipse RCP 以及插件开发的所有文档,而且这些帮助文档基本上都有汉化的版本。
6. 广泛的Java 开发社群支持
Eclipse 本身的开发社区非常庞大,我们可以找到丰富的开发资源和熟悉Eclipse 插件开发的程序员。
7. 强大的企业级背景
Eclipse 本身是由IBM 捐献并成立了Eclipse 基金会,这个基金会的成员包括:BEA 、Borland 、CA 、IBM 、Intel 、Nokia 、Sybase 等等国际企业。这些国际企业或多或少都有基于Eclipse 的产品,特别是IBM 自身,它的很多重要软件产品线都转向Eclipse 平台。
虽然RCP 出现的时间很短,但目前已经有很多大型的应用程序构建在这个强大的平台之上,比较成熟的有IBM Lotus 、Workplace ,Maestro (NASA Space MissionManagement )项目,GumTree (Scientific InstrumentControl )等。Macromedia 最近也宣布他们将用Eclipse RCP 开发下一代富互联网应用(Rich Internet Application ,RIA ) 环境。另外,运行于嵌入式设备的eRCP 也正在如火如荼的开发(目前已经实现了)中。再加上Eclipse 的很多子项目(如BIRT ,DTP ,EMF ,GEF 等),可以说使得基于RCP 的企业级的应用如虎添翼。
用RCP 构建企业级应用一般基于以下的几个流程:
l 构建RCP Application
Eclipse 是一个插件体系结构的完整的应用平台,可以将RCP 看作是一个插件,或一些插件的集合。在EclipseIDE 中,我们新建一个插件项目(Plug-in Project ),并选择这个插件项目是一个RCP 应用程序。一个RCP 应用程序的入口一般需要实现4 个类:
1. org.eclipse.core.runtime.IPlatformRunnable 的实现类
2. org.eclipse.ui.application.WorkbenchAdvisor 的子类
3. org.eclipse.ui.application.WorkbenchWindowAdvisor 的子类
4. org.eclipse.ui.application.ActionBarAdvisor 的子类
应用程序的入口必须实现org.eclipse.core .runtime.applications 扩展点,RCP 也不例外。在Eclipse 启动时, 只能指定一个被运行的application, 这个application 的主类必须实现IplatformRunnable 接口, 由此接口所提供的r u n 方法接管Eclipse 平台的控制权, 当此application 结束时,Eclipse 平台也会退出。
l 构建显示功能
而RCP 的功能主体是由特定透视图所包含的一组视图来呈现。里面所要显示的界面主体主要由透视图所包含的一组视图来呈现,透视图的开发是标准的插件开发,我们可以在已经创建的RCP 应用程序项目下开发,也可以新建一个插件项目来开发。对RCP 应用进行包装(Branding )products 是从3.0 版本以后Eclipse 运行时新提供的一个扩展点,它是基于上节中的applications 扩展点的,除了指定所要运行的应用外,还对一个典型的企业级应用程序的一些重要特性如关于文本,关于Icon ,窗口Icon 及欢迎使用页面等进行了配置,即Branding 功能。RCP 提供了两种不同类型的product 扩展: 静态的和动态的。静态的即我们所使用的类型,在plugin.xml 中直接声明org.eclipse.core.runtime.products 扩展点并设置其所包含的主要配置,比如指定此产品要运行的application (见上节),设置主窗口的图标和标题,关于窗口的图标和文本,闪屏以及所包含的插件等。动态类型的product 扩展需要实现o r g .eclipse.core.runtime.IProductProvider 接口来对提供的一系列产品进行定义。在Eclipse 平台中,features 是一些类似功能或某个产品的一系列plugins 的集合。Features 是可选的功能部件,但是如果你想要使用PDE 来开发的话,这可以提供很大的方便,而且,如果你需要使用Eclipse 提供的自动更新(Update Plugin )功能或使用Java Web Start 来发布你的应用的话,则需要创建一个或多个Feature 。开发业务应用插件前面我们已经介绍了Eclipse RCP 应用的入口程序的开发,入口序完成了两个最重要工作:启动Eclipse Runtime (插件运行时容器)并加载定义好的工作台和默认透视图,而工作台和透视图都是由插件和在入口程序启动E c l i p s eRuntime 之后,所有的业务逻辑和用户交互都由各个插件完成,所以RCP 应用程序的开发实质还是插件的开发。
视图(Views )是RCP 应用程序的重要组成部分,作为一个GUI 应用,界面主要由Views 来呈现。视图的典型角色有下面几种:
1. 为整个应用程序提供一个结构性的概览;
2. 为在Editor (编辑器)中显示的内容提供一个大纲视图(如Outline );
3. 提供上下文相关的信息(如大型应用程序中的Properties 视图)。
在Eclipse 中,可以为Views 定制各种不同的显示方式:1. standalone,2. 不可移动的,3. 不可关闭的,4. 多视图,5. 在Perspective 切换时保持显示的,6. 放置在TabFolder 中的。
l 构建应用交互
ActionBarAdvisor 的子类提供了创建RCP 应用的菜单、工具栏及状态栏的入口。在Eclipse 的世界中,所有的东西都是ContributionItem ,Action 也不例外。可以由两种方式创建R C P 的Action ,菜单项及工具栏等, 一种方法是通过ActionBarAdvisor 来定义, 另外一种是在plugin.xml 中扩展workbench 提供的相应扩展点(org.eclipse.ui.actionSets )并实现IworkbenchWindowActionDelegate 接口来定义。
l 应用程序配置
添加Preferences ,在Eclipse 中,个人喜好页面是由JFace Framework 来提供的,在workbench 中又对其进行了加强,通过在plugin.xml 中扩展相应扩展点org.eclipse.ui.preferencePages )并实现org.eclipse.ui.IworkbenchPreferencePage 接口来定义。在RCP 中,可以使用workbench 中的org.eclipse.ui.actions.ActionFactory 提供的标准Preferences Action 来呼叫出Preference 配置窗口,当此配置窗口显示时,会在Eclipse 运行时的扩展点中查找对应的扩展并将各个配置页面显示出来。
l 添加Help
Eclipse 平台一个优美的地方就是将很多功能部件都设计成为一个Framework ,用户只需做很少量的工作就能实现很复杂的功能,Eclipse 的Help 功能就是一个很好的例子。RCP 的在线帮助采用的是WEB-APP 的方式,Help Framework 的主要工作就是将帮助文档集成进RCP 应用产品的在线帮助中,为了实现这个功能,只需在feature.xml 中添加下面几个插件:org.apache.lucene ,org.eclipse.help.appserver ,org.eclipse.help.base ,org.eclipse.help.ui ,org.eclipse.ui.forms 。
通过在plugin.xml 中扩展help 提供的相应扩展点(org.eclipse.help.toc ),指定所要使用的主题文件,即完成了RCP 应用程序Help 系统的创建工作。
l 发布产品: 打包应用
经过上面的开发步骤,我们的产品已经初具雏形,为了将其提供给用户直接使用,还需要最后一个步骤:打包发布。Eclipse 专门提供了产品配置功能,用于RCP 应用的发布。首先新建一个产品配置文件( 比如:MyRCPApp.product ),在这个产品配置文件中,定义该RCP 应用发布所需要的内容,如:产品的信息和该RCP 产品所包含的插件列表等等, 然后利用Eclipse 的导出功能导出产品。如果想使产品更加专业化, 还可以创建安装程序, 比如使用Install Anywhere 或其它工具将已生成的二进制代码再进行包装, 这样也更加贴近用户的使用感觉。
l 扩展功能
Eclipse 平台的新版本在引入OSGi 特性之后,插件的plugin.xml 文件结构更加清晰,仅仅包含两部分的内容: 所提供的扩展(extension-point )和对已有插件的扩展(extension point )。在前面部分的文章中,我们使用的都是后者,现在我们要自己提供扩展点。首先,需要定义所提供扩展点的Schema, 即其它插件需要扩展时要如何编写扩展; 其次, 在plugin.xml 中声明此扩展点(<extension-point id= ”⋯”name= ”⋯”/> ); 最后,也是最重要的部分, 对所定义的Schema 编程,当读入相应的元素时要如何进行处理。为此,Eclipse 提供了丰富的API 对扩展点进行操作。
l 系统更新
使用Update Manger 更新应用程序为了使我们的产品更专业,提供软件更新功能是很必要的。Eclipse 的Update 部件主要的功能有:
1. 对已有的feature 进行更新;
2. 寻找新的feature 并进行更新;
3. 对已安装的f e a t u r e 进行配置(Enable/Disable )。
RCP 已经成为Java 桌面应用新的生力军,为Rich C/S 模式的回归做好了充分的准备。随着越来越多的国际大厂商(IBM ,BEA ,Oracle ,HP ,CA ,Borland 等)加入到Eclipse 基金会,在Eclipse 的各子项目中分别扮演着越来越重要的角色,相信RCP 会具有一个广泛应用的明天。