异常以及异常处理框架探析异常以及异常处理框架探析
摘要摘要:本文主要与您探讨异常以及异常处理相关方面的一些知识,主要包括检查异常与非检查异常的理解,多视角观察理解异
常,进而探讨关于构建稳健且可扩展的异常框架方面的一些设计原则。
概述
一般情况下,企业级应用都对应着复杂的业务逻辑,为了保证系统的健壮,必然需要面对各种系统业务异常和运行时异常。
不好的异常处理方式容易造成应用程序逻辑混乱,脆弱而难于管理。应用程序中充斥着零散的异常处理代码,使程序代码晦涩
难懂、可读性差,并且难于维护
一个好的异常处理框架能为应用程序的异常处理提供统一的处理视图,把异常处理从程序正常运行逻辑分离出来,以至于提供
更加结构化以及可读性的程序架构。另外,一个好的异常处理框架具备可扩展性,很容易根据具体的异常处理需求,扩展出特
定的异常处理逻辑。
另外,异常处理框架从一定程度上依赖并体现系统架构层次。系统架构决定了系统中各个子系统,各个层次之间的交互,而异
常处理框架则统一体现这种架构中的各种交互所发生的错误、异常。因此,异常处理框架是系统架构时就应该考虑的问题。
本文将对异常相关方面做一些讨论,并进而探讨一些关于构建稳健且可扩展的异常处理框架方面的视角或设计原则。由于本文
引入一部分 Java 语言中异常相关的概念,因此本文假设您熟悉 Java 相关基础知识以及了解 Java EE 和 EJB 相关技术。
Java 异常基本概念
在 Java 程序设计语言中,使用一种异常处理的错误捕获机制。当程序运行过程中发生一些异常情况,程序有可能被中断、或
导致错误的结果出现。在这种情况下,程序不会返回任何值,而是抛出封装了错误信息的对象。Java 语言提供了专门的异常
处理机制去处理这些异常。如图 1 所示为 Java 异常体系结构:
图 1. Java 异常体系结构
检查 (Checked) 异常与非检查 (Unchecked) 异常
Java 语言规范将派生于 Error 类或 RuntimeException 类的所有异常都称为非检查异常。除“非检查异常”以外的所有异常都称
为检查异常。检查异常对方法调用者来说属于必须处理的异常,当一个应用系统定义了大量或者容易产生很多检查异常的方法
调用,程序中会有很多的异常处理代码。
如果一个异常是致命的且不可恢复并且对于捕获该异常的方法根本不知如何处理时,或者捕获这类异常无任何益处,笔者认为
应该定义这类异常为非检查异常,由顶层专门的异常处理程序处理;像数据库连接错误、网络连接错误或者文件打不开等之类
的异常一般均属于非检查异常。这类异常一般与外部环境相关,一旦出现,基本无法有效地处理。
而对于一些具备可以回避异常或预料内可以恢复并存在相应的处理方法的异常,可以定义该类异常为检查异常。像一般由输入
不合法数据引起的异常或者与业务相关的一些异常,基本上属于检查异常。当出现这类异常,一般可以经过有效处理或通过重
试可以恢复正常状态。
由于检查异常属于必须处理的异常,在存在大量的检查异常的程序中,意味着很多的异常处理代码。另外,检查异常也导致破
坏接口方法。如果一个接口上的某个方法已被多处使用,当为这个方法添加一个检查异常时,导致所有调用此方法的代码都需
要修改处理该异常。当然,存在合适数量的检查异常,无疑是比较优雅的,有助于避免许多潜在的错误。
到底何时使用检查异常,何时使用非检查异常,并没有一个绝对的标准,需要依具体情况而定。很多情况,在我们的程序中需
要将检查异常包装成非检查异常抛给顶层程序统一处理;而有些情况,需要将非检查异常包装成检查异常统一抛出。
多视角理解异常
从应用系统最终用户的角度来看,用户所面对的是系统中所提供的各种业务功能以及系统本身的管理功能。用户并不理解系统
内部是如何实现以及如何运行的,与系统开发者存在天然的鸿沟,系统运行对用户来说如同一个黑盒一样。对用户而言,系统
所出现的任何异常或错误,都属于系统运行时异常。对于这些异常,有些异常是用户可以理解并能解决的;而另外一些异常是
用户无法理解和解决的。当一个系统错误出现时,系统本身需要反馈给用户一种可理解的业务相近的信息,从而用户可以根据
这些信息去尽可能解决问题。另一方面,有一类错误属于系统内部运行异常或错误,用户对此类错误根本无能为力。而这类异
常同样需要提供足够详细的信息,系统管理员可根据这类异常尽可能解决。一般情况下,如果异常面向系统用户,以系统异常