Welcome

首页 / 软件开发 / JAVA / 体验Java 1.5中面向方面(AOP)编程

体验Java 1.5中面向方面(AOP)编程2010-12-05对于一个能够访问源代码的经验丰富的Java开发人员来说,任何程序都可以被看作是博物馆里透明的模型。类似线程转储(dump)、方法调用跟踪、断点、切面(profiling)统计表等工具可以让我们了解程序目前正在执行什么操作、刚才做了什么操作、未来将做什么操作。但是在产品环境中情况就没有那么明显了,这些工具一般是不能够使用的,或最多只能由受过训练的者使用。支持团队和最终用户也需要知道在某个时刻应用程序正在执行什么操作。

为了填补这个空缺,我们已经发明了一些简单的替代品,例如日志文件(典型情况下用于服务器处理)和状态条(用于GUI应用程序)。但是,由于这些工具只能捕捉和报告可用信息的一个很小的子集,并且通常必须把这些信息用容易理解的方式表现出来,所以程序员趋向于把它们明确地编写到应用程序中。而这些代码会缠绕着应用程序的业务逻辑,当开发者试图调试或了解核心功能的时候,他们必须"围绕这些代码工作",而且还要记得功能发生改变后更新这些代码。我们希望实现的真正功能是把状态报告集中在某个位置,把单个状态消息作为元数据(metadata)来管理。

在本文中我将考虑使用嵌入GUI应用程序中的状态条组件的情形。我将介绍多种实现这种状态报告的不同方法,从传统的硬编码习惯开始。随后我会介绍Java 1.5的大量新特性,包括注解(annotation)和运行时字节码重构(instrumentation)。

状态管理器(StatusManager)

我的主要目标是建立一个可以嵌入GUI应用程序的JStatusBar Swing组件。图1显示了一个简单的Jframe中状态条的样式。

图1.我们动态生成的状态条

由于我不希望直接在业务逻辑中引用任何GUI组件,我将建立一个StatusManager(状态管理器)来充当状态更新的入口点。实际的通知会被委托给StatusState对象,因此以后可以扩展它以支持多个并发的线程。图2显示了这种安排。

图2. StatusManager和JstatusBar

现在我必须编写代码调用StatusManager的方法来报告应用程序的进程。典型情况下,这些方法调用都分散地贯穿于try-finally代码块中,通常每个方法一个调用。

public void connectToDB (String url) {
StatusManager.push("Connecting to database");
try {
...
} finally {
StatusManager.pop();
}
}

这些代码实现了我们所需要功能,但是在代码库中数十次、甚至于数百次地复制这些代码之后,它看起来就有些混乱了。此外,如果我们希望用一些其它的方式访问这些消息该怎么办呢?在本文的后面部分中,我将定义一个用户友好的异常处理程序,它共享了相同的消息。问题是我把状态消息隐藏在方法的实现之中了,而没有把消息放在消息所属的接口中。