AOP@Work: 用新的 AJDT 本本简化 AOP 开发

发表于:2007-05-24来源:作者:点击数: 标签:AOP@WorkAJDT本本新的简化
AJDT Eclipse 技术项负责人 Matt Chapman 将带您查看 AJDT 1.2 和 AJDT 1.3,它们分别是针对 Eclipse 3.0 和 Eclipse 3.1 的 AspectJ 开发工具的最新版本。这些版本的主要重点是将 AspectJ 与 Eclipse 平台更紧密地集成在一起,并为 AspectJ 开发人员提供更多
AJDT Eclipse 技术项负责人 Matt Chapman 将带您查看 AJDT 1.2 和 AJDT 1.3,它们分别是针对 Eclipse 3.0 和 Eclipse 3.1 的 AspectJ 开发工具的最新版本。这些版本的主要重点是将 AspectJ 与 Eclipse 平台更紧密地集成在一起,并为 AspectJ 开发人员提供更多 Java™ 开发人员使用 Eclipse 时可以得到的高级工具支持。

AspectJ Development Tools for Eclipse (AJDT) 最近经历了相当大的变化,主要是更加全面地与 Eclipse 平台集成在了一起。这一变化为 AspectJ 开发人员提供了对 Eclipse 平台上的工具支持的更多访问。在本文中,我将介绍适用于 Eclipse 3.0 的 AJDT 1.2,它是在今年 6 月发布的,还将介绍适用于 Eclipse 3.1 的 AJDT 1.3,它将于今年 9 月发布(现在可以得到早期的 development builds 版本)。

自 AJDT 1.1 起,AJDT 已经发生了很大变化,所以这篇文章对新接触 AJDT 和熟悉早期版本的开发人员都很有用。在本文中,我不想重复指出发生了什么变化和这些变化是如何发生的,而是打算将用新的观点来观察目前的 AJDT 功能和技术。

在整篇文章中,我都会使用一些常见的场景来探索 AJDT 的功能。所有场景都将反映典型的 AspectJ 开发人员经历的活动;例如,第一个场景涉及如何从头开始创建简单的 AspectJ 项目(开发人员开始熟悉 AspectJ 或者开始熟悉语言和工具时最常做的一件事)。更深入的场景包括:向现有 Java 项目添加方面、处理各种各样的多项目环境。我还将讨论对 AspectJ 5 中新特性的特定支持,并带您经历从 AJDT 1.1 中进行迁移的过程。最后,在对本文进行总结时,我将简要介绍 AJDT 开发过程本身(即用 AJDT 开发 AJDT)以及未来您可以参与的一些变化。

关于本系列

AOP@Work 系列面对的是在面向方面编程上有些基础,同时想扩展或加深这方面了解的开发人员。同 developerWorks 的大多数文章一样,这个系列非常实用:读完每篇介绍新技术的文章之后,即可将其投入使用。

为这个系列选择的每个作者都是面向方面编程领域的领导或专家。许多作者都是系列文章中介绍的项目和工具的参与者。每篇文章都力图提供一个中立的评述,以确保这里表达的观点的公正与正确。

请就文章的评论或问题分别与这些文章的作者联系。要对这个系列整体进行评论,可以与这个系列的负责人 Nicholas Lesiecki 联系。请参阅 参考资料,以获取关于 AOP 的更多背景资料。

请注意,AJDT 1.2 是适用于 Eclipse 3.0 的最新稳定发行版,它替代了 AJDT 1.1.12,而 AJDT 1.3 则是适用于 Eclipse 3.1 的稳定发行版。AJDT 1.2 的 Milestone 版本和 development builds 版本已经可供 Eclipse 3.1 使用,但是要实现适用于 Eclipse 3.1 的稳定发行版,还需要一个独立的版本分支,所以出现了 AJDT 1.3。除了特别指出的之外,本文描述的每件事都适用于两个版本分支。主要的区别在于特定于 AspectJ 5 的功能,它通常要求使用 Eclipse 3.1。

请参阅 参考资料下载 AJDT 和 Eclipse 平台的当前版本。两者都需要下载,以运行本文中的示例。

从头开始学 AJDT

对于刚刚开始接触 AspectJ 的 Java 开发人员,编写一些简单的 AspectJ 程序是一种好的做法。可以使用 AspectJ 编程人员指南中的示例,或者使用众多优秀的 AspectJ 书籍或文章(请参阅 参考资料 一节)来完成这项任务。在 Eclipse 中创建新 AspectJ 项目的过程与创建 Java 项目的过程很相似:只需选择 File > New > Project > AspectJ Project,或者使用工具栏上的 New AspectJ Project 快捷方式即可。向导的其余部分与 New Java Project 向导基本一样。

实际上,AspectJ 项目就是 Java 项目(从 Eclipse 的角度来看,它在具有 AspectJ 性质 之外还具有 Java 性质),所以任何可以在 Java 项目上使用的工具和插件也可以在 AspectJ 项目上操作)。关键的区别是用来编译项目的 Eclipse 构建器:AspectJ 编译器被用来取代 JDT Java 编译器。AspectJ 编译器是 JDT 编译器的扩展,所以完全能够编译 Java 代码。

在下一小节中,我将介绍在简单开发场景中发挥作用的一些 AJDT 特性。

New Aspect 向导

由于 AspectJ 项目和 Java 项目非常相似,所以我不需要解释如何创建源文件夹、包和类,或者如何配置项目的类路径 —— 对于多数 Eclipse Java 开发人员而言,这些都应当是非常自然的事(请参阅 参考资料,以获得有关 Eclipse 的更多信息)。同样,编辑类的体验也与以前一样:仍然可以用 Java 编辑器,并且您会发现一些可以极大地节约时间的特性(像内容辅助、快速修复和组织导入)仍然有效。

所以我们直接介绍下一步:创建方面。方面 是 AspectJ 的模块化单元,与 Java 语言中的类有许多共同之处。请选择 File > New > Other > AspectJ > Aspect 或使用工具栏上的 New Type 下拉列表来打开 New Aspect 向导,它与 New Class 向导非常相似,只有少数选项不同。

AspectJ 编辑器

在创建新方面之后,会看到它在编辑器中打开(这时是 AspectJ 编辑器),您可能会注意到,所创建文件的扩展名是 .aj,这是 AspectJ 中指定的方面扩展名(类保存在 .java 文件中)。请试着在新方面中输入一些 AspectJ 代码。您会发现,编辑器的功能与处理 Java 代码的功能非常相似。例如,请考虑以下特性:

  • 在录入时弹出大纲视图。
  • 在语法错误下面加上了红色的下划线。
  • 组织导入对导入的类进行排序。
  • 编辑器支持重叠显示。
  • 可以重新格式化文件。
  • 通过 control-space 键实现内容辅助在许多情况下都很有帮助。

一切都非常熟悉,不是吗?也有一些事被遗漏,其中包括方面中的快速修复和某些事情的内容辅助(例如切入点名称),这些将由 AJDT 未来的版本解决。

保存方面会导致对项目进行编译(除非禁用了自动构建,如果这样的话,则需要按下 Build 按钮,就像处理 Java 项目那样)。如果方面包含影响项目中的代码的通知(advice),那么应当看到 Cross References 视图中出现一些条目,并且编辑器的左侧会出现一些标记。AJDT 提供了两种向您展示 AspectJ 项目的横切特性的方法。

横切视图

可以将 Cross References 视图和 Outline 视图视为合作伙伴。Outline 视图显示当前文档的结构,而 Cross References 视图显示当前元素的横切关系。一个很有用的布局是将 Cross References 视图放在 Outline 视图下,如下面的图 1 所示。如果看不到这个视图,可以选择 Window > Show View > Other > AspectJ 打开它,或者可以在 Outline 视图中的某个元素上右击,并从上下文菜单中选择 Open Cross References

在编辑器中的方法内部单击会使 Cross References 视图显示该方法的横切信息,如图 1 所示:


图 1. 类的 Outline 和 Cross References 视图
类的 Outline 和 Cross References 视图

在该例中,您可以看到,这个方法正通过 GetInfo 方面中的一些 around 通知来获得消息。可以在通知上单击,以便直接导航到它。然后通知本身就会显示在图 2 所示的 Cross References 视图中,这样就可以从另一个方向查看它们之间的关系:


图 2. 方面的 Outline 和 Cross References 视图
方面的 Outline 和 Cross References 视图

也有选项可以 把 Cross References 视图与编辑器连接。如果采用了这一选项,那么 Cross References 视图不会响应编辑器和 Outline 视图中的选择,如果想一直能够看到某一列横切信息,那么这样做可能很有用。另外一个选项是显示当前文件整体的横切信息,而不仅仅显示当前元素的横切信息。

最后,有些开发人员选择不让 Outline 视图一直可见,因为它会占据宝贵的屏幕空间。相反,他们使用 Quick Outline(从 Navigate 菜单中选择,或者更典型的做法是按下 Ctrl+O),这是该视图的一个权宜版本,出现在编辑器上方。按下 Ctrl+Alt+X(也可以通过 AJDT 选项配置页自己配置键绑定) 将显示 Quick Cross References 视图,如图 3 所示。使用 Quick Outline 视图,再次按下键绑定,这会导致该视图也显示所继承的成员。Quick Cross References 视图使用类似的机制在当前元素的横切信息显示与整个文件的横切信息显示之间进行切换。


图 3. Quick Cross References 视图
Quick Cross References 视图

标记和图像修饰器

如果查看编辑器中建议的源代码,就会看到编辑器左手边的标记图标。这些标记将指出通知的存在和类型,使用的图标与 Outline 和 Cross References 视图中的图标相同。有一些分别表示 before、after 和 around 通知的不同图标。每种图标都有两个变体:有小问号的和没有小问号的。问号表明存在运行时测试,以确定是否在这个位置应用通知,例如什么时候在切入点中使用 cflow 指示器。没有问号的变体用在编译的时候就可以完全确定匹配的地方。

如果在标记上右击,就会在上下文菜单中看到 Advised By entry,以及一个显示通知的来源的子菜单。如果选择其中的一个条目,编辑器会打开并显示这个通知。在通知中会看到额外的标记,这些标记从另一个方向显示横切关系,并且还带有一个 Advises 子菜单,如图 4 所示。这些对称的标记支持在通知的源和目标之间进行一致的导航。类似的标记和子菜单也可以用来表示其他横切信息,例如类型间声明。


图 4. 通知的标记和上下文菜单
通知的标记和上下文菜单

图像装饰器也可以用来表示横切信息。如果回过头来看一下 图 1 所示的 Outline 视图,就会看到在视图的三个方法的左边有一个小的橙色箭头。这个箭头是 Eclipse 用于 Java 元素的图像装饰器。可用它表示指定元素是否受通知的直接影响,或者是否包含正被通知的连接点。这个有帮助的可视线索会在任何 Java 元素出现的地方出现,其中包括 Outline 视图、Cross References 视图和 Java Browsing perspective 中的 Members 视图。





转换 Java 项目

从简单的测试项目得到 AspectJ 和 AJDT 的一些经验之后,开发人员的下一步通常是采用一个现有的 Java 项目,尝试在一个或两个方面扩展它。例如,您可能想添加强制方面,例如检测对 System.out.printlnException.printStackTrace 意外调用的方面,或者 生产方面,例如实现持久性的方面,或者某个设计模式的面向方面实现。

将 Java 项目转换成 AspectJ 项目很简单。只需在项目上右击并选择 Convert to AspectJ Project 即可。从 Eclipse 的角度来说,是将 AspectJ 性质添加到项目中,并转而使用 AspectJ 编译器,就好像从头开始创建 AspectJ 项目那样。这个过程没有什么需要多提的,它可以应用到任何具有 Java 性质的项目上,其中包括更高级的项目,例如 Eclipse 插件项目。这个过程也是可逆的,也就是说,可以使用上下文菜单项来删除 AspectJ 性质并切换回 Java 编译器。

一旦用 AspectJ 项目替代了 Java 项目,您可能想知道它们的区别是什么。至少最初的答案是“它们的区别非常小”。您可以继续在 Java 编辑器中编辑 Java 类,采用标准的文档大纲视图和以前一直使用的所有特性(包括快速修复、内容辅助以及通过红线得到早期错误提示)。同样,把更改保存到类中会导致对项目进行快速递增编译,您也可以从项目的属性页面上设置所有相同的编译器选项。每个合法的 Java 程序都是合法的 AspectJ 程序,所以可以像以前那样编译代码。

实际上,AspectJ 编译器是 Eclipse Java 编译器的扩展,而 AJDT 则尽可能一致、透明地扩展 JDT 工具。这就是我们谈到无缝集成时所指的内容。这是 AJDT 1.2/1.3 的主要重点领域之一,而且我们已经取得了好的进展(我在文章后面部分会指出一些仍然存在的限制)。无缝集成的目标是让切换到 AspectJ 项目的第一步变得尽可能的容易;这为从使用方面进行编码中获得实际有用的东西铺平了道路。





管理多个项目

构建 AspectJ 源代码需要两个不同阶段:编译 .java 和 .aj 文件中的源代码来生成 .class 文件,然后将方面应用到生成的 .class 文件中。第二个阶段称为编织,这是 AspectJ 和 Java 编译器的主要区别。Java 编译过程由类路径设置控制,这使得这些类型可以通过编译器用于解析。AspectJ 编译过程也使用相同的类路径设置,该路径的配置方式与 Eclipse 中的完全相同。但是,这个设置还不足以控制所有情况下的编译和编织步骤。这就是 AspectJ 项目中还有两个额外设置的原因。

首先,有一个 inpath 设置。这里指定的任何内容编织器都可以使用,所以任何应用到的方面都会被编织进来。可以通过在项目上右击并选择 Properties,然后进入 AspectJ InPath 区域,将条目添加到项目的 inpath 中。条目可以是 JAR 文件或目录(类文件夹),例如其他项目的 bin 目录。inpath 中的内容都被发送到项目的输出中,可能是在使用方面编织之后)。

第二个附加选项是 aspectpath。inpath 控制着将要编织的事物的列表,而 aspectpath 控制将那些内容编织到这个列表。换句话说,在 aspectpath 上指定的方面对编织过程是可用的,就好像它们存在于项目源目录中一样。这个设置由 AspectJ Aspect Path 属性页控制,可以包含 JAR 文件或目录。

每个项目的属性页的 AspectJ 区域中还包含 output JAR 设置。这个设置使编译器将类文件直接输出到 JAR 文件,而不是输出到项目的输出文件夹。

使用其他项目的方面

要想查看以上设置的实际效果,请考虑一个示例工作空间。假设有两个项目,一个叫做 MyAspects,另一个叫做 WeaveMe。两者都是 AspectJ 项目,不过第二个本身可能不包含方面。MyAspects 项目包含一些 WeaveMe 项目要求的方面。要连接两个项目,只需在 WeaveMe 项目上右击,然后选择 Properties 并进入 AspectJ Aspect Path 区域即可。接着,在 Libraries 选项卡中按下 Add Class Folder,并选择 MyAspects 项目的 bin 目录(或者任何输出目录对应的名称)。

按下 OK 用这个新设置构建项目,假定方面中的切入点与 WeaveMe 源代码中的位置对应,因此将应用对应的通知。编辑器的标记和 Cross References 视图仍会显示“advised by”关系,但是现在关系的始发端被描述为一个二进制方面,所以不能导航到它。这是因为一般来说,方面可以位于 Eclipse 工作空间以外的地方(例如外部 JAR文件)。但是,至少在这个示例中,源代码仍然在工作空间之内,只不过是在另一个项目中,所以希望 AJDT 的未来版本能够做好这个连接,并允许导航到其他项目中的方面。

需要着重指出的是,通过 aspectpath 提供的类型在运行时也需要能够使用。幸运的是,AJDT 使这一点变得很容易 —— 不必选择 Run > Java Application,可以使用新的启动配置 Run > AspectJ/Java Application。这与 Java 启动配置相同,惟一区别是它自动向运行时类路径添加了 aspectpath 条目。另外,还有一个无关的区别是,AspectJ/Java 启动配置也可以定位到方面中包含的任何主方法。

编织 Java 项目

如果有一个项目包含 Java 代码,或者以源代码的形式,或者以 JAR 文件的形式,倘若现在想在它上面应用某些方面,那么该怎么办呢?如果需要保持方面与项目分离,那么可以把它单独作为一个 Java 项目,并创建一个 AspectJ 项目进行编织。在这种情况下,只要在 AspectJ 项目中添加“AspectJ InPath”设置并引用 Java 代码即可,可以使用 Add JARs 或 Add Class Folder 按钮添加设置。

在像这样进行二进制编织的时候,没有源代码标记来显示通知发挥效果的地方。编译器选项在这里会有帮助:在 AspectJ 项目的 AspectJ Compiler 设置的 Other 选项卡中(或者从全局选项参数设置中),选择 Output weaving info messages to problems view 选项。现在,不论何时构建项目,Problems 视图都会显示信息条目,指出编织进去了哪些类型,如图 5 所示:


图 5. 编织信息消息
编织信息消息

注意,如果输入的是 JAR 文件,那么可能要使用前面提到的 Output JAR 选项直接生成初始 JAR 文件的编织后版本。

开发 Aspect 库

可重用方面库的概念是一个非常强大的概念。假设已经开发了一个方面,并且感觉它适用于其他项目,那么可以泛化这个方面,并把它隔离到自己独立的项目中,形成一个库。通常,库中的方面应当定义适当的行为,然后可以根据需要将它裁剪为符合特定目的。这很有可能涉及一个带有抽象切入点的抽象方面。然后,使用方面的项目就可以用切入点扩展它,切入点定义了将要应用的方面的适当范围。

如果使用方面库的项目包含任何必要的抽象方面的具体版本,那么只需要从 Java Build Path 属性页将库项目添加到 Projects 选项卡中,就可以把两个项目连接起来。由于具体方面对项目而言是本地的,所以常规的类路径查找就足以解决超方面的问题。

还要注意的是,编辑器标记和 Cross References 视图把通知的源显示为抽象超类。这样做是正确的,因为这就是通知所在的位置;但是在这种情况下,具体方面中的切入点控制着通知的应用,而这常常是一个很有趣的地方。在 AJDT 的未来版本中,可能会公开“使用切入点(uses pointcut)”来帮助实现这个连接。由于可重用方面库的潜力,所以可以预期,在 AJDT 后续的发行版中,这一领域的通用支持会有所增加。

处理插件项目

Eclipse 平台的日益流行意味着越来越多的开发人员在构建插件。好消息是使用 AspectJ 处理插件很容易。只需采用一个插件项目,在该项目上右击,并用与处理 Java 项目相同的方式将它转换成 AspectJ 项目即可。系统会提示您添加对 org.aspectj.runtime 插件的依赖关系。AspectJ 程序在运行时对 aspectjrt.jar 文件存在依赖,而对于插件项目来说,这个依赖关系可以通过小的 org.aspectj.runtime 插件来满足。将这个依赖关系添加到项目之后,就可以在未来的插件开发中使用方面了。

集成的限制

在几个领域中,AJDT 与 Eclipse 其余部分的集成并不是无缝的,例如在插件的示例中,除了现有的 Create Ant Build File 选项外,还添加了 Create Ant Build File with AspectJ Support。Eclipse 插件应当提供附加功能而不是替代现有功能,但是在这个示例中,如果能把现有功能扩展到处理 AspectJ 项目,当然更好。这样用户在 Java 和 AspectJ 项目中就只会看到一个 Create Ant Build File 选项,而且在两种情况下,两个项目都可以工作。在这里,最好的方式是对 Eclipse 的基函数提出增强请求,让它可以扩展,因为这类通用目的的扩展很有意义。

Eclipse 插件开发环境 (Plug-in Development Environment,PDE) 允许为插件项目生成 Ant 构建文件(build.xml)。AJDT 为支持 AspectJ 的插件项目提供了类似选项。在 plugin.xml 文件上右击,并选择 PDE Tools > Create Ant Build File with AspectJ Support。生成的 build.xml 文件与为 Java 插件项目生成的文件类似,差别在于不使用 javac Ant 任务编译源代码,而是用 AspectJ 提供的 iajc 任务。





管理大项目

现在您已经看到,在 Eclipse 平台上用 AJDT 创建简单项目是多么容易,并且我们还查看了如何将 Java 项目迁移到 AJDT,如何用 AJDT 管理、处理多个项目和项目类型。接下来,我将介绍一些特别适合具有大量源文件的项目的 AJDT 特性,并提供一些使用它们的技巧。

项目级可视化

正如前面看到的,AspectJ 编辑器中的标记和 Cross References 视图清楚地在每个文件的基础上表现出了横切的特性。无法从这些特性中得到的只是对关注点的广泛分布的总体概括 —— 例如,它是否横切整个项目或只是横切几个包。要想得到这类观察,可以使用 Visualiser。

打开 Visualiser 最简单的方式就是切换到 Aspect Visualization 视图,它代表选中项目的可视化表示,所选中项目由一些列组成,一个源文件一栏,列的高度与源文件的行数成正比。栏上不同位置的条带被涂上了不同的颜色,用来表示通知发挥作用的源代码位置(在进行其他运行时测试的情况下,可能会发挥作用)。每个条带的颜色对应着包含这条通知的方面。可以在图 6 的屏幕快照中看到这一点:


图 6. Visualiser
Visualiser

可以看到,有一个主 Visualiser 视图和一个辅助 Visualiser Menu 视图,这个视图中列出了被显示的方面。可以从列表中取消对方面的选择,把它们从可视化中删除。例如,您可能想删除一个到处都有、挡住其他方面的日志方面。可以用 Visualiser 视图工具栏上的控件放大或缩小视图,使内容适合于视图(有一个最小尺寸的限制),或者只显示受通知影响的栏(不受影响的栏以灰色显示),并把分组级别从类视图切换到包视图(在包视图中,包中的所有类都被组合到一栏中)。最后,可以使用下拉菜单访问其他选项,例如参数设置页,在这里,可以进一步对呈现方式进行定制。除了显示通知的效果之外,可视化还包括“declare error”和“declare warning”语句位置的匹配。可以从 Visualiser 菜单的工具栏中切换这些选项的开关。用来表示不同方面的颜色也可以从列表中进行修改,而选中的颜色会被记住。

Visualiser 的设计目标是处理大型项目,虽然要求用同样多的处理来决定每个类的大小并使其可视化。由于可用的图形内存通常比通用内存更有限,所以已经对呈现过程进行了优化,将图形内存的使用控制在最小。只在需要栏的时候才呈现它们,所以第一次滚动视图时不像之后滚动它时那么顺畅。通用内存用于缓存图片数据,除非通用内存不足。在内存不足时,每次都会重新生成图像数据。这意味着更大的项目也能显示,但是由于内存有限,在滚动时,响应可能不是很快。

Visualiser 支持一个选择机制,该机制可以通过鼠标或键盘操作来选择栏、类或条带。激活某一个选择(通过双击鼠标,或按下空格键)会让对应的项目在编辑器中打开。值得指出的是:Visualiser 实际是一个完全通用的组件,可以将它更改为能够对任何东西(从 Eclipse 标记到 Google 搜索结果)进行可视化。除了向 Visualiser 提供定制数据之外,还可以定制栏的绘制样式和条带使用的颜色。请参阅 参考资料,以获得更多信息。

管理变化

项目的开发过程中,代码中不断发生变化。随着代码的重构、bug 的修补和新特性的实现,类和方法不断被添加、删除和改名。在大型项目中管理这些变化是非常具有挑战性的,特别是在有大量横切功能的时候。可以用方面捕获这个功能,由于把相关代码收集在一起,而不是散落在代码基的各处,所以可以改善这种状况。然后可以用切入点来定义将在其上应用方面中的通知的连接点。但是,随着上述变化不断发生,甚至连匹配位置也可能发生意想不到的变化。

解决这个问题的第一个方法是从一起开始就开发健壮的切入点。在更改代码之后,构建良好的切入点不太可能停止匹配所需的位置。例如,如果对调用采用 integer 作为自己的第一个参数的 update 方法感兴趣,那么可以使用 call(* update(int)) 这样的切入点。它会与所有带有单一 integer 参数的 update 方法调用进行匹配。但是,如果后来有人向该方法中添加了其他参数,切入点就不再匹配。如果只对第一个 integer 参数感兴趣,那么更好的切入点应当是 call(* update(int,..)),因为即使添加或删除额外参数,这个切入点仍然会匹配。

即使有这些预防措施,有些类型的变化仍然可能给最健壮的切入点带来问题;例如,在以上示例中,方法参数可能这样变化:您所感兴趣的 integer 不再是第一个参数。另外一种变化可能造成切入点在更多地方开始进行匹配,而不是在所要求的地方。例如,如果对 setter 方法感兴趣,那么切入点中可能应用了 set* 模式,但是后来代码中添加了一个叫做 setup 的非 setter 方法,这会造成切入点意料之外的额外匹配。

新的 横切比较(Crosscutting Comparison) 功能(及时为 AJDT 1.2.1 和 1.3 版本添加的功能)—— 就是为了帮助处理代码的这类变化而开发的。横切比较允许对项目中的横切关系制作一个快照,然后用快照与该项目以后的版本中存在的关系进行比较。要创建快照,请在项目上右击,然后选择 AspectJ Tools > Save Crosscutting Map。系统会提示输入保存关系图的文件名。这些文件的扩展名是 .ajmap,可以将这些文件直接保存在项目中。例如,在发布项目的某个具体版本时,可以保存这个发行版的横切关系,以便在开发下一发行版时将它们作为参考点。

一旦项目中有了一个或多个横切图文件,就可以进行比较了。可以用两个文件相互比较,也可以用一个文件中的关系与当前构建中存在的关系进行比较。要使用这两个选项,可以在包浏览器中选择一个或二个图文件,然后从上下文菜单中选择适当的选项。比较的结果会在新视图中显示出来,如图 7 所示:


图 7. 横切比较视图
横切比较视图

这个视图显示了自从第一个图文件记录以来添加的横切关系,以及删除的关系(即在第个图文件或当前构建中不存在的关系)。可以双击源和目标元素,在编辑器中打开它们(当然,不存在的元素除外)。在工具栏上有一个过滤器按钮,可以限制显示的关系集。默认情况下只显示一个方向的关系,例如,显示了“advises”,就不同时显示“advised by”。您还可以单击栏标题,根据这一栏对结果进行排序。最后要注意的是,如果选择了用图文件与当前构建进行比较,那么每次进行构建时,就会重新进行比较。这可以提供有关创建图文件以后发生的变化的持续观察,这在重构项目中的代码时非常有用。

内存使用

一般来说,AspectJ 项目使用的内存在两个方面要比 Java 项目使用的内存多。首先,是在编译器上。面向方面的编译器所做的工作要比面向对象的编译器做的工作多得多,因为它要执行编织过程。第二,开发环境需要额外的工作才能让应用程序的横切结构显现出来。虽然这个负荷不能完全避免,但 AJDT 和 AspectJ 编译器的未来发行版会重点减少它。

如果正在处理大型项目,那么要采取的第一步通常是改进运行 Eclipse 的 Java 进程的内存总量。要做到这点,可以向 Eclipse 进程传递一个参数,比如 -vmargs -Xmx512m。如果不需要同时打开工作空间中的所有项目,那么可以关闭其中一些项目。如果仍然发现内存不足,那么可以对项目进行安排,例如有些代码是通过 Java 编译器编译的,包含通过二进制编织或加载时编织应用的一些方面。另一个选项是使用 AspectJ 编译器设置的“Other”选项卡,在每项目基础上,或者在整个工作空间范围内,禁用横切结构模型的创建。这样做可以节省内存,但是应当只将此作为最后一种方法使用,因为如果这样做,就看不到任何通知标记,而 Cross References 和 Visualiser 视图也不会显示任何横切信息。





AspectJ 5 中的新内容

正如我前面提到过的,多数特定于 AspectJ 5 的功能只在 Eclipse 3.1 中才有,因为它要求的 Java 5 支持在 Eclipse 3.0 中不存在。所以,除非特别指出,否则这一节中的内容只适用于 AJDT 1.3。上个月的 AOP@Work 系列“AspectJ 5 简介”介绍了 AspectJ 5 中的新特性,所以在这里只讨论它们对 AJDT 的意义。但是,请注意,在 AspectJ 项目中使用 Java 5 模型所需的步骤与 Java 项目中的相同。选择 Java > Compiler,然后将 compiler compliance level 设置为 5.0。还需要保证项目的构建目录中的 JRE 系统库是 Java 5 的系统库,而不是 1.4.2 或更早的版本。

AspectJ 5 中的少数变化不需要 AJDT 做任何变化,例如语义变化或附加的 API 类。有些变化,例如新的 pertypewithin 方面实例化模型,只要求高亮显示编辑器中的语法,而且在这种情况下,在 New Aspect 向导中会出现额外的复选框。其他变化要求的工作略多一些,您很快就会看到。还需要注意的是,在许多情况下,AJDT 开发小组已经首先实现了最底级别的支持,留下了日后添加更多功能的空间。

添加到 Java 5 和 AspectJ 5 中的注释已经广为人知。因为 AJDT 扩展了 Eclipse 中的 JDT,所以它自动得到了这里添加的注释支持的好处。AspectJ 5 添加了新的切入点指示器,例如根据注释是否存在而进行匹配的 @this。这些要求在编辑器中高亮显示语法。AspectJ 5 中还添加了一种新的声明语句,用来在类型、方法、构造函数和字段上声明注释。通过添加了两个新的横切关系“annotates” 和“annotated by”,新的声明语句在 AJDT 中受到支持,它们显示在 Cross References 视图和标记的上下文菜单中,就像“advises”和“advised by”那样。

在图 8 中可以看到新的声明语句的简单示例。其中的方面包含一条 declare @method 语句和一个类型间声明。方面被选中,所以 Cross References 视图显示方面中每件事的横切信息。declare @method 语句注释了三个方法 —— 一个是类型间声明,另外两个直接在 Aclearcase/" target="_blank" >ccount 类中。类型间声明被显示为“declared on”(在...上声明)在 Account 类上,而且由 @method 声明“annotated by”(由...标注)。还请注意,编辑器中 @method 声明的标记和类型间声明上的双向箭头,因为它既是横切关系的源,也是目标。


图 8. 在 AspectJ 5 中声明注释
在 AspectJ 5 中声明注释

AspectJ 5 的另外一个新特性是对基于注释样式的方面声明的支持,这一样式被称作“@AspectJ”样式。这样,就可以通过普通的 Java 5 编译器编译 AspectJ 应用程序,然后再由 AspectJ 编织器对其进行编织。作为例子,我们没有使用常规代码样式语法中的 pointcut 关键字,而是定义了一个普通的 Java 方法,然后在定义切入点的方法上附加一个 Java 5 注释。图 9 显示了这样的一个示例。可以看到,不管使用的开发样式如何,AJDT 仍然显示了应用程序的横切结构。


图 9. @AspectJ 开发样式
@AspectJ 开发样式




从 AJDT 1.1 迁移

考虑到 AJDT 1.2 和 1.3 中的变化的范围,以及大量的内部重构,把原来采用 AJDT 1.1 Eclipse 工作空间升级会是一个相当复杂的过程,可能并不让人惊讶。但是 AJDT 开发团队已经通过引入迁移向导使这一过程尽可能的顺利,如图 10 所示。在升级 AJDT 版本之后,第一次运行 Eclipse 时会出现向导。在执行升级之前,应该打开想要包含在迁移过程中的项目,还应当关闭 AspectJ 编辑器的所有实例,因为 AspectJ 编辑器已经发生变化。(如果没有关闭编辑器的实例,只会得到“cannot restore editor”错误,您可以放心地忽略这一错误。)


图 10. 迁移向导
迁移向导

迁移向导的第一页将根据需要对源文件的扩展名进行转换,例如方面(以及任何包含切入点或内部方面的类)终止于 .aj 文件。如果需要,可以将项目排除在这个过程之外。请注意,在 AJDT 中,有一个转换向导负责稍后根据需要对文件扩展名进行转换;在单个项目或单个源文件上右击可以找到这个向导。迁移向导的下一页将指出,对于 Eclipse builder for AJDT 而言,哪一部分变化才是主要的内部变化。在这里,不能接受默认设置的惟一情况就是:想使用兼容性模式,让项目仍然可以作为一个 AJDT 1.1 项目使用的时候。向导的第三页只针对那些启用了 AspectJ 的插件项目:对大型的 org.aspectj.ajde 插件不再存在运行时依赖,现在依赖的是新的、非常小的 org.aspectj.runtime 插件。下一页将取消 AJDT 1.1 所做的所有全局工作空间设置,最后一页将引入新的 Cross References 视图。





AJDT 开发注意事项

近一年以来,我们 AJDT 项目团队一直使用 AspectJ 和 AJDT 开发 AJDT。AJDT 是由数量不断增长的启用 AspectJ 的插件实现的。由于许多开发人员已经在更大型的项目(大约有了 200,000 行代码)中使用了 AJDT,所以 AJDT 经历了合理的测试(除了大量 JUnit 测试和手工测试场景之外),这意味着我们能够在您遭遇大量问题之前发现和修补它们。

使用 AOP (具体地说是 AspectJ 和 AJDT) 开发 AJDT 并将它与 Eclipse 集成,帮助我们把重点放在最需要的修补和增强上:最初,我们的生产率可能因转换而降低,但是现在,我们的经验让我们更加感谢 AJDT 和 AspectJ 的增强。

完全出于这些原因,转换是值得进行,当然,我们也期望同时从 AOP 得到一些好处!刚开始时,通过利用方面捕捉异常和向 Eclipse 的错误日志写入适当条目,我们提高了诊断问题的能力 —— 在此之前,我们得手工异常处理,在应当处理异常的地方,有一半的地方遗漏了!我们还可以启用一个监视方面,它将填充一个视图,在 Visualiser 中显示各种性能和资源使用测量情况。方面也可以用在 AJDT 中,强制实施编码标准,跟踪对多个属性页的变化,以及用 Eclipse 的 ISafeRunnable 接口包装调用。最好的消息可能是:所有这些都仅仅是开始,在不远的未来,我们期望让方面变成 AJDT 新功能设计的基本部分。





AJDT 的未来

如果您熟悉 AJDT 早期的版本,那么您现在可能已经看到在 AJDT 1.2 和 1.3 中很多东西都已经发生了变化。现在回到 AJDT 1.1,AspectJ 编辑器能力很弱,但却既可以用于编辑类,也可以用于编辑方面,定制的大纲视图比标准 Java 大纲视图要弱一些。对比之下,新的 AspectJ 编辑器为编辑方面提供了更丰富的体验,用标准的 Java 编辑器编辑类,标准的大纲视图得到增强,现在可以支持方面。这也意味着用参数配置向导对工作空间进行全局设置修改不再是必需的。

关系到 ajdoc 的生成的功能以及对构建配置的支持在很大程度上并没有发生改变,但是大多数领域都得到了改进和扩展。现在有一些显示和导航程序的横切结构的新方法,还有一些对导出到 JAR 文件、转换文件扩展名和创建构建文件的新支持,以及对递增编译(现在是默认设置)以及处理更大项目的更灵活的 Visualiser 的明显支持。文档已经被彻底革新,以帮助您从 AJDT 得到最大好处。

尽管有这些进展,仍然有许多事要做。首先,是与 Eclipse 的集成问题:从长远来看,健壮的、全面集成的 AJDT 要求 Eclipse 中的 Java 工具要比目前更具扩展性,我们希望我们开发 AJDT 的经验能在这一领域有所贡献。其次,我们总有更多特性可以开发,以增强 AspectJ 的工具。这些包括面向方面的重构、对开发和使用方面库的增强支持,以及开发更多处理“信息过载”的方法 —— 例如在项目中增加对 AspectJ 的使用时,会造成过量的横切标记。AJDT 仍然由用户需求驱动,所以请告诉我们您需要哪些功能,哪些 bug 给您带来了最大问题。如果您想参与其中,请定位到 AJDT 的主页(参阅 参考资料),查看 Bugzilla 的链接、新闻组、开发人员邮件列表和 to-do 任务页面。

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)