Eclipse体系结构介绍(一)

实现软件模块化是一项众所周知的艰巨任务。与多元化社区编写的大型代码库的互操作性也很难管理。在Eclipse,我们在两个方面都取得了成功。 2010年6月,Eclipse基金会推出了Helios协调发布版,其中包括来自40多家公司的39个项目和490个提交者,他们共同致力于构建基础平台的功能。 Eclipse最初的架构愿景是什么?它是如何演变的?应用程序的体系结构如何用于鼓励社区参与和增长?让我们回到开头。

2001年11月7日,一个名为Eclipse 1.0的开源项目发布。当时,Eclipse被描述为“用于任何事物的集成开发环境(IDE),特别是没有任何东西。”这种描述是故意通用的,因为架构愿景不仅仅是另一套工具,而是一个框架;一个模块化和可扩展的框架。 Eclipse提供了一个基于组件的平台,可以作为为开发人员构建工具的基础。这种可扩展的架构鼓励社区建立一个核心平台,并将其扩展到原始愿景的极限之外。 Eclipse最初是一个平台,Eclipse SDK是概念验证产品。 Eclipse SDK允许开发人员自托管并使用Eclipse SDK本身来构建更新版本的Eclipse。

开源开发人员的陈规定型形象是一个利他主义的人,他们深夜工作,修复错误并实现梦幻般的新功能以满足他们自己的个人兴趣。相比之下,如果回顾一下Eclipse项目的早期历史,那么捐赠的一些初始代码基于IBM开发的VisualAge for Java。从事这个开源项目的第一批提交者是IBM子公司Object Technology International(OTI)的员工。这些提交者获得了全职工作在开源项目上的工作,回答有关新闻组的问题,解决错误并实现新功能。成立了一个由感兴趣的软件供应商组成的联盟,以扩展这种开放式工具。 Eclipse联盟的初始成员是Borland,IBM,Merant,QNX Software Systems,Rational Software,RedHat,SuSE和TogetherSoft。

通过投资这些努力,这些公司将拥有基于Eclipse的商业产品的专业知识。这类似于公司为Linux内核做出贡献的投资,因为让员工改进作为其商业产品基础的开源软件符合他们的自身利益。 2004年初,Eclipse基金会成立,旨在管理和扩展不断发展的Eclipse社区。这个非营利性基金会由企业会员会费提供资金,并由董事会管理。今天,Eclipse社区的多样性已经扩展到包括170多个成员公司和近1000个提交者。

最初,人们只知道“Eclipse”作为SDK,但今天它更多。 2010年7月,eclipse.org正在开发250个不同的项目。有支持使用C / C ++,PHP,Web服务,模型驱动开发,构建工具等开发的工具。这些项目中的每一个都包含在一个顶级项目(TLP)中,该项目由项目管理委员会(PMC)管理,该项目由项目的高级成员组成,负责设定技术指导和发布目标。为简洁起见,本章的范围仅限于Eclipse1和Runtime Equinox2项目中Eclipse SDK体系结构的演变。由于Eclipse历史悠久,我将专注于早期的Eclipse,以及3.0,3.4和4.0版本。

6.1 早期的Eclipse

在21世纪初,软件开发人员有许多工具,但很少有人一起工作。 Eclipse试图为应用程序开发人员提供一个开源平台,用于创建可互操作的工具。这将允许开发人员专注于编写新工具,而不是编写代码来处理基础设施问题,例如与文件系统交互,提供软件更新以及连接到源代码存储库。 Eclipse可能是Java开发工具(JDT)最着名的。目的是这些示例性Java开发工具将作为有兴趣为其他语言提供工具的人的示例。

在我们深入研究Eclipse的体系结构之前,让我们看一下Eclipse SDK对开发人员的看法。在启动Eclipse并选择工作台时,您将看到Java透视图。透视图组织特定于当前正在使用的工具的视图和编辑器。

[Java Perspective]

                                               图6.1:Java透视图 

早期版本的Eclipse SDK体系结构有三个主要元素,分别对应三个主要子项目:平台,JDT(Java开发工具)和PDE(插件开发环境)。

6.1.1 平台

Eclipse平台是使用Java编写的,运行它需要Java VM。它由称为插件的小功能单元构建而成。插件是Eclipse组件模型的基础。插件本质上是一个JAR文件,其中包含一个描述自身,其依赖关系以及如何使用或扩展它的清单。此清单信息最初存储在插件文件中,该文件位于插件目录的根目录中。 Java开发工具提供了用Java开发的插件。插件开发环境(PDE)提供了用于开发插件以扩展Eclipse的工具。 Eclipse插件是用Java编写的,但也可能包含非代码贡献,例如用于联机文档的HTML文件。每个插件都有自己的类加载器。插件可以通过在plugin.xml中使用requires语句来表达对其他插件的依赖性。查看org.eclipse.ui插件的plugin.xml,您可以看到它的名称和版本,以及从其他插件导入所需的依赖项。

<?xml version="1.0" encoding="UTF-8"?>
<plugin
   id="org.eclipse.ui"
   name="%Plugin.name"
   version="2.1.1"
   provider-name="%Plugin.providerName"
   class="org.eclipse.ui.internal.UIPlugin">

   <runtime>
      <library name="ui.jar">
         <export name="*"/>
         <packages prefixes="org.eclipse.ui"/>
      </library>
   </runtime>
   <requires>
      <import plugin="org.apache.xerces"/>
      <import plugin="org.eclipse.core.resources"/>
      <import plugin="org.eclipse.update.core"/>
      :       :        :
      <import plugin="org.eclipse.text" export="true"/>
      <import plugin="org.eclipse.ui.workbench.texteditor" export="true"/>
      <import plugin="org.eclipse.ui.editors" export="true"/>
   </requires>
</plugin>

为了鼓励人们在Eclipse平台上构建,需要有一种机制来为平台做出贡献,并且平台需要接受这种贡献。这是通过使用扩展和扩展点(Eclipse组件模型的另一个元素)来实现的。导出标识了您希望其他人在编写扩展时使用的接口,这会将插件外部可用的类限制为导出的类。它还对插件外部可用的资源提供了额外的限制,而不是让所有公共方法或类可供消费者使用。导出的插件被视为公共API。所有其他人都被视为私人实施细节。要编写一个可以为Eclipse工具栏提供菜单项的插件,可以使用org.eclipse.ui插件中的actionSets扩展点。

<extension-point id="actionSets" name="%ExtPoint.actionSets"
                 schema="schema/actionSets.exsd"/>
<extension-point id="commands" name="%ExtPoint.commands"
                 schema="schema/commands.exsd"/>
<extension-point id="contexts" name="%ExtPoint.contexts"
                 schema="schema/contexts.exsd"/>
<extension-point id="decorators" name="%ExtPoint.decorators"
                 schema="schema/decorators.exsd"/>
<extension-point id="dropActions" name="%ExtPoint.dropActions"
                 schema="schema/dropActions.exsd"/> =

您的插件扩展为org.eclipse.ui.actionSet扩展点提供菜单项将如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<plugin
   id="com.example.helloworld"
   name="com.example.helloworld"
   version="1.0.0">
   <runtime>
      <library name="helloworld.jar"/>
   </runtime>
   <requires>
      <import plugin="org.eclipse.ui"/>
   </requires>
   <extension
         point="org.eclipse.ui.actionSets">
      <actionSet
            label="Example Action Set"
            visible="true"
            id="org.eclipse.helloworld.actionSet">
         <menu
               label="Example &Menu"
               id="exampleMenu">
            <separator
                  name="exampleGroup">
            </separator>
         </menu>
         <action
               label="&Example Action"
               icon="icons/example.gif"
               tooltip="Hello, Eclipse world"
               class="com.example.helloworld.actions.ExampleAction"
               menubarPath="exampleMenu/exampleGroup"
               toolbarPath="exampleGroup"
               id="org.eclipse.helloworld.actions.ExampleAction">
         </action>
      </actionSet>
   </extension>
</plugin>

当Eclipse启动时,运行时平台会扫描安装中插件的清单,并构建一个存储在内存中的插件注册表。扩展点和相应的扩展名按名称进行映射。生成的插件注册表可以从Eclipse平台提供的API中引用。注册表缓存到磁盘,以便下次重新启动Eclipse时可以重新加载此信息。启动时会发现所有插件以填充注册表,但在实际使用代码之前,它们不会被激活(加载类)。这种方法称为延迟激活。通过在实际需要时实际加载与插件关联的类,可以减少在安装中添加其他软件包对性能的影响。例如,在用户选择工具栏中的新菜单项之前,不会激活有助于org.eclipse.ui.actionSet扩展点的插件。

[Example Menu]

                     图6.2 示例菜单

生成此菜单项的代码如下所示:

package com.example.helloworld.actions;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.jface.dialogs.MessageDialog;

public class ExampleAction implements IWorkbenchWindowActionDelegate {
    private IWorkbenchWindow window;

    public ExampleAction() {
    }

    public void run(IAction action) {
        MessageDialog.openInformation(
            window.getShell(),
            "org.eclipse.helloworld",
            "Hello, Eclipse architecture world");
    }

    public void selectionChanged(IAction action, ISelection selection) {
    }

    public void dispose() {
    }

    public void init(IWorkbenchWindow window) {
        this.window = window;
    }
}

一旦用户选择工具栏中的新项目,扩展注册表将由实现扩展点的插件查询。提供扩展的插件实例化贡献,并加载插件。激活插件后,运行示例中的ExampleAction构造函数,然后初始化Workbench操作委托。由于工作台中的选择已更改且已创建委托,因此操作可能会更改。将打开消息对话框,其中显示消息“Hello,Eclipse architecture world”。

这种可扩展的体系结构是Eclipse生态系统成功发展的关键之一。公司或个人可以开发新的插件,并将其作为开源发布或商业销售。

关于Eclipse最重要的概念之一就是一切都是插件。无论插件是否包含在Eclipse平台中,或者您自己编写插件,插件都是组装应用程序的第一类组件。图6.3显示了Eclipse早期版本中插件所贡献的相关功能集群。

[Early Eclipse Architecture]

                                            图6.3 早期Eclipse架构

工作台是Eclipse平台用户最熟悉的UI元素,因为它提供了组织Eclipse在桌面上显示给用户的方式的结构。工作台由透视图,视图和编辑器组成。编辑器与文件类型相关联,因此在打开文件时会启动正确的编辑器。视图的一个示例是“问题”视图,它指示Java代码中的错误或警告。编辑和视图共同构成了一种视角,以有组织的方式向用户呈现工具。

Eclipse工作台是基于标准窗口小部件工具包(SWT)和JFace构建的,SWT值得进行一些探索。窗口小部件工具包通常被分类为本机或模拟。本机窗口小部件工具包使用操作系统调用来构建用户界面组件,例如列表和按钮。与组件的交互由操作系统处理。模拟的小部件工具包实现操作系统之外的组件,处理鼠标和键盘,绘图,焦点和其他小部件功能本身,而不是推迟到操作系统。两种设计都有不同的优点和缺点。

原生小工具工具包是“像素完美”。他们的小部件外观和感觉就像桌面上其他应用程序中的对应部分。操作系统供应商不断更改其小部件的外观并添加新功能。原生小部件工具包免费获得这些更新。遗憾的是,本机工具包很难实现,因为它们的底层操作系统小部件实现差别很大,导致不一致和不可移植的程序。

模拟小部件工具包要么提供自己的外观,要么尝试绘制和操作类似于操作系统。它们优于本机工具包的强大之处在于灵活性(尽管现代本机小部件工具包,如Windows Presentation Framework(WPF)同样具有灵活性)。因为实现窗口小部件的代码是工具包的一部分而不是嵌入在操作系统中,所以可以使窗口小部件以任何方式绘制和表现。使用模拟小部件工具包的程序非常便于移植。早期模拟的widget工具包声誉不佳。它们通常很慢并且在模拟操作系统方面表现不佳,使它们在桌面上看起来不合适。特别是,由于使用模拟小部件,当时的Smalltalk-80程序很容易识别。用户意识到他们正在运行“Smalltalk程序”,这会伤害对Smalltalk编写的应用程序的接受。

与其他计算机语言(如C和C ++)不同,Java的第一个版本附带了一个名为Abstract Window Toolkit(AWT)的本机窗口小部件工具包库。 AWT被认为是有限的,越野车和不一致的,并被广泛谴责。在Sun和其他地方,部分原因是由于使用AWT的经验,一个可移植和高性能的本机窗口小部件工具包被认为是不可行的。解决方案是Swing,一个功能齐全的模拟小部件工具包。

大约在1999年,OTI使用Java来实现一个名为VisualAge Micro Edition的产品。 VisualAge Micro Edition的第一个版本使用Swing和OTI的Swing经验并不积极。 Swing的早期版本有错误,有时间和内存问题,当时的硬件功能不足以提供可接受的性能。 OTI已成功为Smalltalk-80和其他Smalltalk实现构建了一个本机小部件工具包,以获得Smalltalk的认可。此体验用于构建SWT的第一个版本。 VisualAge Micro Edition和SWT取得了成功,当Eclipse开始工作时,SWT是自然的选择。在Eclipse中使用SwT over Swing拆分了Java社区。有些人看到了阴谋,但Eclipse取得了成功,使用SWT将其与其他Java程序区分开来。 Eclipse是高性能的,像素完美的,一般的情绪是,“我不敢相信它是一个Java程序。”

早期的Eclipse SDK在Linux和Windows上运行。 2010年,支持十几个平台。开发人员可以为一个平台编写应用程序,并将其部署到多个平台。为Java开发新的widget工具包是当时Java社区中一个有争议的问题,但Eclipse提交者认为在桌面上提供最佳的本机体验是值得的。这个断言今天适用,并且有数百万行代码依赖于SWT。

JFace是SWT之上的一个层,它为常见的UI编程任务提供工具,例如首选项和向导的框架。与SWT一样,它设计用于许多窗口系统。但是,它是纯Java代码,不包含任何本机平台代码。

该平台还提供了一个基于称为主题的小型信息单元的集成帮助系统。主题由标签和对其位置的引用组成。该位置可以是HTML文档文件,也可以是描述其他链接的XML文档。主题在目录(TOC)中组合在一起。将主题视为叶子,将TOC视为组织的分支。要向应用程序添加帮助内容,您可以为org.eclipse.help.toc扩展点做出贡献,如下面的org.eclipse.platform.doc.isv plugin.xml所示。

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>

<!-- ===================================================================== -->
<!-- Define primary TOC                                                    -->
<!-- ===================================================================== -->
   <extension
         point="org.eclipse.help.toc">
      <toc
            file="toc.xml"
            primary="true">
      </toc>
      <index path="index"/>
   </extension>
<!-- ===================================================================== -->
<!-- Define TOCs                                                           -->
<!-- ===================================================================== -->
   <extension
         point="org.eclipse.help.toc">
      <toc
            file="topics_Guide.xml">
      </toc>
      <toc
            file="topics_Reference.xml">
      </toc>
      <toc
            file="topics_Porting.xml">
      </toc>
      <toc
            file="topics_Questions.xml">
      </toc>
      <toc
            file="topics_Samples.xml">
      </toc>
   </extension>

Apache Lucene用于索引和搜索在线帮助内容。在早期版本的Eclipse中,联机帮助作为Tomcat Web应用程序提供。此外,通过在Eclipse本身内提供帮助,您还可以使用帮助插件的子集来提供独立的帮助服务器

Eclipse还提供团队支持,以与源代码存储库交互,创建补丁和其他常见任务。工作区提供了文件和元数据的集合,用于将您的工作存储在文件系统中。还有一个用于跟踪Java代码中的问题的调试器,以及用于构建特定于语言的调试器的框架。

Eclipse项目的目标之一是鼓励该技术的开源和商业用户扩展平台以满足他们的需求,鼓励这种采用的一种方法是提供稳定的API。 API可以被视为指定应用程序行为的技术合同。它也可以被认为是一种社会契约。在Eclipse项目中,口头禅是“API永远”。因此,在编写API时必须仔细考虑,因为它意味着无限期使用。稳定的API是客户端或API使用者与提供者之间的契约。此合同确保客户端可以依赖Eclipse平台长期提供API,而无需客户端进行痛苦的重构。一个好的API也足够灵活,可以实现不断发展。

6.1.2 Java开发工具(JDT)

JDT提供Java编辑器,向导,重构支持,调试器,编译器和增量构建器。编译器还用于内容辅助,导航和其他编辑功能。 Eclipse不附带Java SDK,因此用户可以选择在其桌面上安装哪个SDK。为什么JDT团队编写了一个单独的编译器来编译Eclipse中的Java代码?他们有VisualAge Micro Edition的初始编译器代码贡献。他们计划在编译器之上构建工具,因此编写编译器本身是一个合乎逻辑的决定。此方法还允许JDT提交者提供扩展编译器的扩展点。如果编译器是第三方提供的命令行应用程序,那将很困难。

编写自己的编译器提供了一种机制,可以在IDE中为增量构建器提供支持。增量构建器提供了更好的性能,因为它只重新编译已更改的文件或其依赖项。增量构建器如何工作?在Eclipse中创建Java项目时,您将在工作空间中创建资源来存储文件。 Eclipse中的构建器获取工作区内的输入(.java文件),并创建输出(.class文件)。通过构建状态,构建器知道工作空间中的类型(类或接口)以及它们如何相互引用。每次编译源文件时,编译器都会向构建器提供构建状态。调用增量构建时,将为构建器提供资源增量,该资源增量描述任何新的,已修改或已删除的文件。删除的源文件删除了相应的类文件。新的或修改的类型将添加到队列中。队列中的文件按顺序编译,并与旧类文件进行比较,以确定是否存在结构更改。结构更改是对类的修改,可能会影响引用它的另一种类型。例如,更改方法签名,或添加或删除方法。如果存在结构更改,则引用它的所有类型也会添加到队列中。如果类型已完全更改,则新类文件将写入构建输出文件夹。使用编译类型的参考信息更新构建状态。对队列中的所有类型重复此过程,直到为空。如果存在编译错误,Java编辑器将创建问题标记。多年来,JDT提供的工具与Java运行时本身的新版本一起得到了极大的扩展。

6.1.3 插件开发环境(PDE)

插件开发环境(PDE)提供了用于开发,构建,部署和测试用于扩展Eclipse功能的插件和其他工件的工具。由于Eclipse插件是Java世界中的一种新型工件,因此没有可以将源转换为插件的构建系统。因此,PDE团队编写了一个名为PDE Build的组件,该组件检查了插件的依赖关系并生成了Ant脚本来构建构建工件。

原文链接

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值