Throwable的子类在构造器中可以接受一个cause(因由)对象作为参数。这个cause就是用来表示原始异常,这样通过把原始异常传递给新的异常,使得即使在当前位置创建并抛出了新的异常,也能通过这个异常链追踪到异常最初发生的位置。
示例
/**
* 重新抛出异常
* @author yan
*
*/
public class Rethrowing {
//模拟dao层异常
public static void dao() throws Exception {
System.out.println("originating the exception in dao()");
throw new Exception("thrown from dao()");
}
//模拟service层
public static void service() throws Exception {
try {
dao();
} catch (Exception e) {
System.out.println("Exception inside service(), Caused by: ");
e.printStackTrace();
throw e;//此异常对象是原始异常对象,持有全部站轨迹信息
}
}
//模拟Controller层
public static void controller() throws Exception{
try {
service();
} catch (Exception e) {
System.out.println("Exception inside controller(), Caused by: ");
e.printStackTrace();
//更新调用栈信息,抛出的异常对象中包含的是重新抛出点的信息,有关原来异常发生点的信息会丢失。
//会丢失原异常抛出点到当前抛出点的栈轨迹
//throw (Exception)e.fillInStackTrace();
//以此异常为cause构造新的异常并抛出,可通过这个异常链追踪到异常最初发生的位置
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
try {
service();
} catch (Exception e) {
System.err.println("Exception1:");
e.printStackTrace();
}
try {
controller();
} catch (Exception e) {
System.err.println("Exception2:");
e.printStackTrace();
}
}
}
执行信息如下:
备注:不知道具体什么原因,直接执行示例代码输出内容是混乱的,一步一步debug才能得到上述输出结果。
写完这个示例,大概可以猜测spring等框架的异常信息是怎么捕获的了。