Java 1.5中面向方面(AOP)编程[组图](6)
异常的处理
文章前面提到,我希望编写附加的代码使用不同目的的@Status注解。我们来考虑一下一些额外的需求:我们的应用程序必须捕捉所有的未处理异常并把它们显示给用户。但是,我们不是提供Java堆栈跟踪,而是显示拥有@Status注解的方法,而且还不应该显示任何代码(类或方法的名称或行号等等)。
例如,考虑下面的堆栈跟踪信息:
java.lang.RuntimeException: Could not load data for symbol IBM
at boxpeeking.code.YourCode.loadData(Unknown Source)
at boxpeeking.code.YourCode.go(Unknown Source)
at boxpeeking.yourcode.ui.Main+2.run(Unknown Source)
at java.lang.Thread.run(Thread.java:566)
Caused by: java.lang.RuntimeException: Timed out
at boxpeeking.code.YourCode.connectToDB(Unknown Source)
... 更多信息
这将导致图1中所示的GUI弹出框,上面的例子假设你的YourCode.loadData()、YourCode.go()和YourCode.connectToDB()都含有@Status注解。请注意,异常的次序是相反的,因此用户最先得到的是最详细的信息。
图3.显示在错误对话框中的堆栈跟踪信息
为了实现这些功能,我必须对已有的代码进行稍微的修改。首先,为了确保在运行时@Status注解是可以看到的,我就必须再次更新@Retention,把它设置为@Retention(RetentionPolicy.RUNTIME)。请记住,@Retention控制着JVM什么时候抛弃注解信息。这样的设置意味着注解不仅可以被编译器插入字节码中,还能够使用新的Method.getAnnotation(Class)方法通过反射来进行访问。
现在我需要安排接收代码中没有明确处理的任何异常的通知了。在Java 1.4中,处理任何特定线程上未处理异常的最好方法是使用ThreadGroup子类并给该类型的ThreadGroup添加自己的新线程。但是Java 1.5提供了额外的功能。我可以定义UncaughtExceptionHandler接口的一个实例,并为任何特定的线程(或所有线程)注册它。
请注意,在例子中为特定异常注册可能更好,但是在Java 1.5.0beta1(#4986764)中有一个bug,它使这样操作无法进行。但是为所有线程设置一个处理程序是可以工作的,因此我就这样操作了。
现在我们拥有了一种截取未处理异常的方法了,并且这些异常必须被报告给用户。在GUI应用程序中,典型情况下这样的操作是通过弹出一个包含整个堆栈跟踪信息或简单消息的模式对话框来实现的。在例子中,我希望在产生异常的时候显示一个消息,但是我希望提供堆栈的@Status描述而不是类和方法的名称。为了实现这个目的,我简单地在Thread的StackTraceElement数组中查询,找到与每个框架相关的java.lang.reflect.Method对象,并查询它的堆栈注解列表。不幸的是,它只提供了方法的名称,没有提供方法的特征量(signature),因此这种技术不支持名称相同的(但@Status注解不同的)重载方法。
实现这种方法的示例代码可以在peekinginside-pt2.tar.gz文件的/code/04_exceptions目录中找到。
- 上一篇:Java串行端口技术协议[组图]
- 下一篇:Java堆的管理--垃圾回收