Java 1.5中面向方面(AOP)编程[组图](8)
前面提到的取样方法的一个问题是它不能区分长时间运行的方法与在循环中多次调用的方法。由于重构会给每次方法调用增加一定的开销,我们有必要忽略频繁调用的方法。幸运的是,我们可以使用重构解决这个问题。除了简单地更新StatusManager之外,我们将维护每个重构的方法被调用的次数。如果这个数值超过了某个极限(意味着维护这个方法的信息的开销太大了),取样线程将会永远地取消对该方法的重构。
理想情况下,我将把每个方法的调用数量存储在重构过程中添加到类的新字段中。不幸的是,Java 1.5中增加的类转换机制不允许这样操作;它不能增加或删除任何字段。作为代替,我将把这些信息存储在新的CallCounter类的Method对象的静态映射中。
这种混合的方法可以在示例代码的/code/06_dynamic目录中找到。
概括
图4提供了一个矩形,它显示了我给出的例子相关的特性和代价。
图4.重构方法的分析
你可以发现,动态的(Dynamic)方法是各种方案的良好组合。与使用重构的所有示例类似,它提供了方法开始或终止时刻的明确的回调,因此你的应用程序可以准确地跟踪运行时并立即为用户提供反馈信息。但是,它还能够取消某种方法的重构(它被过于频繁地调用),因此它不会受到其它的重构方案遇到的性能问题的影响。它没有包含编译时步骤,并且它没有增加类载入过程中的额外的工作。
未来的趋势
我们可以给这个项目增加大量的附件特性,使它更加适用。其中最有用的特性可能是动态的状态信息。我们可以使用新的java.util.Formatter类把类似printf的模式替换(pattern substitution)用于@Status消息中。例如,我们的connectToDB(String url)方法中的@Status("Connecting to %s")注解可以把URL作为消息的一部分报告给用户。
在源代码重构的帮助下,这可能显得微不足道,因为我将使用的Formatter.format方法使用了可变参数(Java 1.5中增加的"魔术"功能)。重构过的版本类似下面的情形:
public void connectToDB (String url) {
Formatter f = new Formatter();
String message = f.format("Connecting to %s", url);
StatusManager.push(message);
try {
...
} finally {
StatusManager.pop();
}
}
- 上一篇:Java串行端口技术协议[组图]
- 下一篇:Java堆的管理--垃圾回收