開發(fā)中 我們 需要對 異常 進行 捕獲處理。
某些地方 會 對異常進行全局 攔截處理,時常遇到 的 問題是,異常"迷路"了。
沒有根據(jù)設(shè)定 ,被特定的異常處理器進行處理,如:
業(yè)務(wù)下層定義了 一個 UserException。
經(jīng)過層層調(diào)用,系統(tǒng)最上層 希望 統(tǒng)一捕獲UserException 進行全局處理,但是層層 調(diào)用后,原本的UserException無法 通過 catch(UserException e) 捕獲了。
很常見的一個的 原因 就 是 被“吃”了。被InvocationTargetException 吃了。
我們時常使用的 包括 spring在內(nèi)的 高級 框架 會 在方法調(diào)用的時候,進行"加料",方法不一定是簡單的直接調(diào)用執(zhí)行,方法 可能 被 通過 反射 執(zhí)行。
示例代碼如下
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class TestException extends Exception {
TestException(String s) {
super(s);
}
}
class Reflected {
public void run(int i) throws TestException {
if (i < 0) {
throw new TestException("涼涼");
}
System.out.println("參數(shù):" + i);
}
}
/**
* @author dongbin
*/
public class ReflectTest {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("cn.qingtui.Reflected");
Method method = clazz.getMethod("run", int.class);
method.invoke(clazz.newInstance(), -1);
} catch (InvocationTargetException e) {
System.out.println("此處接收被調(diào)用方法內(nèi)部未被捕獲的異常");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
輸出結(jié)果 如下
此處接收被調(diào)用方法內(nèi)部未被捕獲的異常
此處接收被調(diào)用方法內(nèi)部未被捕獲的異常
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at im.qingtui.app.tms.ReflectTest.main(ReflectTest.java:32)
Caused by: im.qingtui.app.tms.TestException: 涼涼
at cn.qingtui.Reflected.run(ReflectTest.java:17)
... 5 more
catch的時候 會走到 catch (InvocationTargetException e) 分支 。
可能的想法 是 ,我 直接 catch(TestException e) 能捕獲到嗎?
答: 編譯不過,因為 try的代碼塊里 沒有 任何地方 throw TestException,所以不能catch

解決辦法
從異常的 堆棧信息可知,原本要拋出的 異常會被InvocationTargetException“吃”進了肚子里,信息會被保留。
開發(fā)的 時候 記得,如果方法 被 反射執(zhí)行了,那異常處理的時候,則 需要 使用
InvocationTargetException.getTarget()
拿到原始異常,再進行處理。
需要注意的 是 InvocationTargetException.getTarget()的返回類型是 Throwable。
換句話說,你get到以后 不能 直接 知道 異常的 類型,需要寫 一系列的 判斷 代碼 來 識別 里面的內(nèi)容 具體是 什么異常。
比較 常見的 尷尬局面 是 ,下層 業(yè)務(wù) 拋出的 gezho0ng1異常 ,最后 都變成了 InvocationTargetException。
上層需要 挨個 if else 判斷(不能 switch case),具體要對 異常 如何 處理。
面對這種局面,如何 優(yōu)雅的 處理?歡迎 各位 大佬 評論區(qū)留言。