¿Es así como se esperaría que se comporte Spring MVC?
A partir de Spring 4.3.7, así es como se comporta Spring MVC: usa HandlerExceptionResolverinstancias para manejar excepciones lanzadas por métodos de controlador.
De forma predeterminada, la configuración de MVC web registra un solo HandlerExceptionResolverbean, a HandlerExceptionResolverComposite, que
delegados a una lista de otros HandlerExceptionResolvers.
Esos otros resolutores son
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
registrado en ese orden. A los efectos de esta pregunta solo nos preocupamos ExceptionHandlerExceptionResolver.
Una AbstractHandlerMethodExceptionResolverque resuelve excepciones a través de @ExceptionHandlermétodos.
En la inicialización del contexto, Spring generará un ControllerAdviceBeanpara cada @ControllerAdviceclase anotada que detecte. Los ExceptionHandlerExceptionResolverrecuperará del contexto y los ordenará usando el AnnotationAwareOrderComparatorque
es una extensión de OrderComparatorque admite la Ordered
interfaz de Spring, así como las anotaciones @Ordery @Priority, con un valor de orden proporcionado por una instancia Ordenada que anula un valor de anotación definido estáticamente (si lo hubiera).
Luego registrará un ExceptionHandlerMethodResolverpara cada una de estas ControllerAdviceBeaninstancias (mapeando los @ExceptionHandlermétodos disponibles a los tipos de excepción que deben manejar). Estos finalmente se agregan en el mismo orden a a LinkedHashMap(que conserva el orden de iteración).
Cuando ocurre una excepción, ExceptionHandlerExceptionResolveriterará a través de estos ExceptionHandlerMethodResolvery usará el primero que pueda manejar la excepción.
Entonces, el punto aquí es: si tiene una @ControllerAdvicecon una @ExceptionHandlerpara, Exceptionse registra antes que otra @ControllerAdviceclase con una @ExceptionHandlerpara una excepción más específica, como IOException, se llamará a la primera. Como se mencionó anteriormente, puede controlar ese orden de registro haciendo que su @ControllerAdviceclase anotada implemente Orderedo anotándola con @Ordero @Priorityy dándole un valor apropiado.
@ExceptionHandlermétodos dentro de a@ControllerAdvice, se elige el que maneja la superclase más específica de la excepción lanzada.