ExceptionHandlerExceptionResolver处理异常过程总结
- Spring MVC 执行Controller方法异常后,在分发器DispatcherServlet的doDispatch方法中catch住异常,然后将异常交给processHandlerException方法处理,
- 循环遍历已加载的异常处理器(HandlerExceptionResolver)的实现类,执行resolveException方法
- 内部逻辑会走到doResolveHandlerMethodException(一般异常都会交给ExceptionHandlerExceptionResolver实现类处理)
- 在getExceptionHandlerMethod方法内部根据用户调用Controller中相应的方法得到HandlerMethod,根据得到的HandlerMethod从缓存(exceptionHandlerCache)中查找是当前应用程序抛出的异常否有对应的异常解析器,如果有则使用缓存命中的,如果没有则新构造ExceptionHandlerMethodResolver对象,通过ExceptionHandlerMethodResolver对象获取对应的异常处理方法,如果获取到对应的异常处理方法,则用该方法处理异常;
- 如果没有对应的异常处理方法,则遍历被@ControllerAdvice注解的bean(每个bean对应一个ExceptionHandlerMethodResolver),从遍历出的ExceptionHandlerMethodResolver对象获取对应的异常处理方法,如果获取到对应的异常处理方法,则用该方法处理异常;
- 这里异常还有个优先级的问题,比如发生的是NullPointerException,但是声明的异常有Throwable和Exception,这时候ExceptionHandlerMethodResolver找Method的时候会根据异常的最近继承关系找到继承深度最浅的那个异常,即Exception。另外Controller内部定义了异常处理方法,优先选择Controller内部的异常处理方法处理异常
说明
- 构造ExceptionHandlerMethodResolver有2种选择,
- 1、接口请求发生异常时。通过HandlerMethod拿到Controller,创建ExceptionHandlerMethodResolver并缓存当前Controller对应的ExceptionHandlerMethodResolver到exceptionHandlerCache,并且会找到Controller方法中带有@ExceptionHandler注解的方法(这个异常处理针对对应Controller方法执行时抛出的异常)
- 2、在容器启动时。找到@ControllerAdvice注解配置的类,创建ExceptionHandlerMethodResolver对象并缓存到exceptionHandlerAdviceCache中,ExceptionHandlerMethodResolver对象创建的过程中会记录带有@ExceptionHandler注解的方法。(这个异常处理是针对全局的,所有匹配的Controller)
- ExceptionHandlerMethodResolver是一个会在Class及Class的父类集合中找出带有@ExceptionHandler注解的类,该类带有key为Throwable,value为Method的缓存属性。
- ExceptionHandlerMethodResolver中有1个key为Throwable,value为Method(异常对应的处理方法)的缓存对象mappedMethods。