Это то, как можно ожидать поведения Spring MVC?
Начиная с Spring 4.3.7, Spring MVC ведет себя следующим образом: он использует HandlerExceptionResolver
экземпляры для обработки исключений, генерируемых методами обработчика.
По умолчанию конфигурация веб-MVC регистрирует один HandlerExceptionResolver
bean-компонент a HandlerExceptionResolverComposite
, который
делегаты к списку других HandlerExceptionResolvers
.
Остальные резолверы
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
зарегистрированы в таком порядке. Мы заботимся только об этом вопросе ExceptionHandlerExceptionResolver
.
Объект, AbstractHandlerMethodExceptionResolver
который разрешает исключения с помощью @ExceptionHandler
методов.
При инициализации контекста Spring будет генерировать a ControllerAdviceBean
для каждого @ControllerAdvice
обнаруженного аннотированного класса. Они ExceptionHandlerExceptionResolver
будут извлекать их из контекста и сортировать их, используя AnnotationAwareOrderComparator
which
является расширением , OrderComparator
которое поддерживает в Spring Ordered
интерфейс, а также @Order
и @Priority
аннотаций, со значением порядка , предоставленной упорядоченном например Переопределение статически определенное значение аннотаций (если таковые имеются).
Затем он зарегистрирует ExceptionHandlerMethodResolver
для каждого из этих ControllerAdviceBean
экземпляров (сопоставив доступные @ExceptionHandler
методы с типами исключений, которые они должны обрабатывать). Наконец, они добавляются в том же порядке к LinkedHashMap
(что сохраняет порядок итераций).
Когда возникает исключение, он ExceptionHandlerExceptionResolver
будет перебирать их ExceptionHandlerMethodResolver
и использовать первый, который может обработать исключение.
Итак, суть в следующем: если у вас есть объект @ControllerAdvice
с @ExceptionHandler
for, Exception
который регистрируется перед другим @ControllerAdvice
классом с @ExceptionHandler
более конкретным исключением, например IOException
, будет вызван первый класс . Как упоминалось ранее, вы можете управлять этим порядком регистрации, @ControllerAdvice
реализуя свой аннотированный класс Ordered
или аннотируя его с помощью @Order
или @Priority
и давая ему соответствующее значение.
@ExceptionHandler
методов в a@ControllerAdvice
выбирается тот, который обрабатывает наиболее конкретный суперкласс созданного исключения.