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