ExceptionHandlerExceptionResolver處理異常過程總結(jié)
- Spring MVC 執(zhí)行Controller方法異常后,在分發(fā)器DispatcherServlet的doDispatch方法中catch住異常,然后將異常交給processHandlerException方法處理,
- 循環(huán)遍歷已加載的異常處理器(HandlerExceptionResolver)的實現(xiàn)類,執(zhí)行resolveException方法
- 內(nèi)部邏輯會走到doResolveHandlerMethodException(一般異常都會交給ExceptionHandlerExceptionResolver實現(xiàn)類處理)
- 在getExceptionHandlerMethod方法內(nèi)部根據(jù)用戶調(diào)用Controller中相應(yīng)的方法得到HandlerMethod,根據(jù)得到的HandlerMethod從緩存(exceptionHandlerCache)中查找是當(dāng)前應(yīng)用程序拋出的異常否有對應(yīng)的異常解析器,如果有則使用緩存命中的,如果沒有則新構(gòu)造ExceptionHandlerMethodResolver對象,通過ExceptionHandlerMethodResolver對象獲取對應(yīng)的異常處理方法,如果獲取到對應(yīng)的異常處理方法,則用該方法處理異常;
- 如果沒有對應(yīng)的異常處理方法,則遍歷被@ControllerAdvice注解的bean(每個bean對應(yīng)一個ExceptionHandlerMethodResolver),從遍歷出的ExceptionHandlerMethodResolver對象獲取對應(yīng)的異常處理方法,如果獲取到對應(yīng)的異常處理方法,則用該方法處理異常;
- 這里異常還有個優(yōu)先級的問題,比如發(fā)生的是NullPointerException,但是聲明的異常有Throwable和Exception,這時候ExceptionHandlerMethodResolver找Method的時候會根據(jù)異常的最近繼承關(guān)系找到繼承深度最淺的那個異常,即Exception。另外Controller內(nèi)部定義了異常處理方法,優(yōu)先選擇Controller內(nèi)部的異常處理方法處理異常
說明
- 構(gòu)造ExceptionHandlerMethodResolver有2種選擇,
- 1、接口請求發(fā)生異常時。通過HandlerMethod拿到Controller,創(chuàng)建ExceptionHandlerMethodResolver并緩存當(dāng)前Controller對應(yīng)的ExceptionHandlerMethodResolver到exceptionHandlerCache,并且會找到Controller方法中帶有@ExceptionHandler注解的方法(這個異常處理針對對應(yīng)Controller方法執(zhí)行時拋出的異常)
- 2、在容器啟動時。找到@ControllerAdvice注解配置的類,創(chuàng)建ExceptionHandlerMethodResolver對象并緩存到exceptionHandlerAdviceCache中,ExceptionHandlerMethodResolver對象創(chuàng)建的過程中會記錄帶有@ExceptionHandler注解的方法。(這個異常處理是針對全局的,所有匹配的Controller)
- ExceptionHandlerMethodResolver是一個會在Class及Class的父類集合中找出帶有@ExceptionHandler注解的類,該類帶有key為Throwable,value為Method的緩存屬性。
- ExceptionHandlerMethodResolver中有1個key為Throwable,value為Method(異常對應(yīng)的處理方法)的緩存對象mappedMethods。