可插拔异常处理程序
可插拔异常处理程序是一种允许组件的用户自定义该组件的异常处理的技术。代替处理,丰富,包装和/或者记录异常,将异常处理委托给异常处理程序。这是异常处理程序接口在代码中的外观:
public interface ExceptionHandler {
public void handle(Exception e, String errorMessage);
}
这是一个使用它的类:
public class Component{
protected ExceptionHandler exceptionHandler = null;
public void setExceptionHandler(ExceptionHandler handler){
this.exceptionHandler = handler;
}
public void processFile(String fileName){
FileInputStream input = null;
try{
input = new FileInputStream(fileName);
processStream(input);
} catch (IOException e){
this.exceptionHandler.handle(e,
"error processing file: " + fileName);
}
}
protected void processStream(InputStream input)
throws IOException{
//do something with the stream.
}
}
注意processFile方法中的catch子句如何不包装,重新抛出或者记录捕获的IOException。异常将传递给ExceptionHandler实例的handle()方法。然后,异常处理程序可以决定如何处理它。应该忽略该异常吗?记录了吗?软件包在另一个异常中?还是只是按原样重新投放?异常处理程序可以自行决定。但是请注意,异常处理程序无法抛出在捕获异常的方法中未声明的检查异常。例如,processFile方法不声明任何检查的异常。因此,ExceptionHandler的handle()方法不能引发任何检查的异常。但是,ExceptionHandler可以抛出它想要的所有未经检查的异常(RuntimeException及其子类)。
其中使用可插拔异常处理程序?
在可以以不同方式明智地处理发生的异常的情况下,可插拔异常处理程序最有效。例如,在验证XML文档或者HTML表单时,我们可能并不总是希望在第一个验证错误时停止验证。在某些情况下,我们可能希望继续验证以捕获所有引发的验证异常,并同时将所有异常显示给用户。这样可以使用户免于纠正错误,验证,纠正错误,反复验证的麻烦。一次迭代即可捕获并纠正所有错误。
执行
Java中没有标准的ExceptionHandler接口。我们将必须定义自己,以匹配组件或者应用程序的需求。 ExceptionHandler的handle方法应采用多少个参数,取决于组件要尝试执行的操作。但至少,我建议我们使用捕获的异常和说明错误发生时尝试执行的操作的文本。
提供ExceptionHandler接口的默认实现,并用其实例初始化组件是个好主意。在所需的异常处理与默认实现所提供的相同的情况下,这使组件的用户不必插入异常处理程序。例如,默认实现可能只是抛出异常,或者将其包装在特定于组件的异常中。
程式码范例
这是异常处理程序的一些示例。
public class IgnoringHandler implements ExceptionHandler{
public void handle(Exception e, String message) {
//do nothing, just ignore the exception
}
}
public class WrappingHandler implements ExceptionHandler{
public void handle(Exception e, String message){
throw new RuntimeException(message, e);
}
}
public class CollectingHandler implements ExceptionHandler{
List exceptions = new ArrayList();
public List getExceptions(){ return this.exceptions; }
public void handle(Exception e, String message){
this.exceptions.add(e);
//message is ignored here, but could have been
//collected too.
}
}

