SpringBoot自定义异常源码分析
SpringBoot自定義異常源碼分析
?
在類上加ControllerAdvice注解,在方法上加ExceptionHandler注解,就可以在方法里處理相應(yīng)的異常。
1.自定義異常處理類AdditionalExceptionHandler
掛@RestControllerAdvice注解:
------------------
2.自定義異常處理類GlobalExceptionHandler
=======================
初始調(diào)用鏈
main函數(shù)出發(fā)refreshContext
調(diào)用refresh
?進入context
?
AbstractApplicationContext調(diào)用beanFactory
getBean
?
org.springframework.beans.factory.support包下的一系列factory調(diào)用:
?SimpleInstantiationStrategy類的
instantiate方法觸發(fā)對WebMvcAutoConfiguration的反射
WebMvcAutoConfiguration類
configureHandlerExceptionResolvers方法
調(diào)用addDefaultHandlerExceptionResolvers(exceptionResolvers);
addDefaultHandlerExceptionResolvers類
調(diào)用exceptionHandlerResolver.afterPropertiesSet();
ExceptionHandlerExceptionResolver類的
afterPropertiesSet()調(diào)用initExceptionHandlerAdviceCache()
-----------------
異常核心處理類ExceptionHandlerExceptionResolver類
這個類掃描了所有標注有ExceptionHandler注解的方法,并將他們存入exceptionHandlerAdviceCache中
------------
initExceptionHandlerAdviceCache方法
先找到異常注解的bean
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
對其循環(huán)
for (ControllerAdviceBean adviceBean : adviceBeans)
判斷是否有異常映射
if (resolver.hasExceptionMappings())
放到異常句柄緩存
this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
-----------------------
ControllerAdviceBean類的findAnnotatedBeans方法找到@ControllerAdvice注解的bean
findAnnotatedBeans流式編程findAnnotationOnBean判斷是否是ControllerAdvice.class
?
------------------------
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);
調(diào)用ExceptionHandlerMethodResolver,這里就是
遍歷自定義異常類AdditionalExceptionHandler (參考1)的方法method
-------------------
selectMethods判斷是否有ExceptionHandler注解
------
這個MethodIntrospector類的selectMethods很復(fù)雜
Select methods on the given target type based on the lookup of associated metadata.
查找給定類型的方法
>>>
selectMethods調(diào)用ReflectionUtils.doWithMethods
<<<回到selectMethods判斷是否橋接方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {methodMap.put(specificMethod, result);
}
什么時候會生成橋接方法
那什么時候編譯器會生成橋接方法呢?可以查看JLS中的描述http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.4.5。
就是說一個子類在繼承(或?qū)崿F(xiàn))一個父類(或接口)的泛型方法時,在子類中明確指定了泛型類型,那么在編譯時編譯器會自動生成橋接方法
------------------------
最關(guān)鍵就是EXCEPTION_HANDLER_METHODS
EXCEPTION_HANDLER_METHODS判斷是否有ExceptionHandler注解,
回過來看AdditionalExceptionHandler自定義異常定義了有ExceptionHandler注解的方法
--------------------
ExceptionHandlerMethodResolver的addExceptionMapping的put操作:
=====================
hasExceptionMappings判斷方法:
mappedMethods定義:
?
看看mappedMethods的調(diào)用,直接點或者Ctrl+Alt+H都可以看到變量調(diào)用點:
--------------
?
this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
?
如果覺得前面的分析比較繁瑣,這個寫的比較簡潔可以參考下
https://juejin.im/post/5cad5143f265da03b20413a6
==========================
【異常的觸發(fā)】
前面講了異常的注解初始化的時候掃描,現(xiàn)在我們故意觸發(fā)一段異常。
json數(shù)據(jù)格式異常觸發(fā)fastjson異常。這個異常被
DispatcherServlet的doDispatch捕獲
processDispatchResult結(jié)果處理
判斷是否是異常,是異常進行異常處理processHandlerException
遍歷handlerExceptionResolvers。
?
進入
protected final ModelAndView doResolveException
再進入doResolveHandlerMethodException
getExceptionHandlerMethod
異常判斷
異常類型判斷
resolveMethod調(diào)用resolveMethodByThrowable
異常命中以后
ServletInvocableHandlerMethod(advice.resolveBean(), method);
進入HandlerMethod
回到
doResolveHandlerMethodException
進入
exceptionHandlerMethod.invokeAndHandle
開始反射執(zhí)行自定義的全局異常
bean就是之前定義的GlobalExceptionHandler
進入自定義的異常處理方法
封裝返回對象
一直返回多次回到
invokeAndHandle
返回ModelAndView()
返回
回到processRequest
經(jīng)過一系列的FilterChain
回到tomcat的代碼做輸出了
總結(jié)
以上是生活随笔為你收集整理的SpringBoot自定义异常源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一般做一个CT多少钱
- 下一篇: Java的List和Json转换以及St