Невже так можна очікувати, що Spring MVC поводитиметься?
Станом на Spring 4.3.7, ось як поводиться Spring MVC: він використовує HandlerExceptionResolver
екземпляри для обробки винятків, виданих методами обробника.
За замовчуванням веб-конфігурація MVC реєструє один HandlerExceptionResolver
компонент a HandlerExceptionResolverComposite
, який
делегатів до списку інших HandlerExceptionResolvers
.
Ці інші вирішувачі
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
зареєстровано в такому порядку. Для цілей цього питання ми лише піклуємось ExceptionHandlerExceptionResolver
.
Те, AbstractHandlerMethodExceptionResolver
що вирішує винятки за допомогою @ExceptionHandler
методів.
При ініціалізації контексту Spring генерує ControllerAdviceBean
для кожного @ControllerAdvice
анотованого класу, який виявляє. ExceptionHandlerExceptionResolver
Буде витягувати їх з контексту, і сортувати їх , використовуючи при допомоги AnnotationAwareOrderComparator
яких
є розширенням, OrderComparator
яке підтримує Ordered
інтерфейс Spring, а також анотації @Order
and @Priority
, зі значенням замовлення, що надається впорядкованим екземпляром, замінюючи статично визначене значення анотації (якщо воно є).
Потім він реєструє ExceptionHandlerMethodResolver
для кожного з цих ControllerAdviceBean
екземплярів (зіставлення доступних @ExceptionHandler
методів із типами винятків, з якими вони мають працювати). Вони нарешті додаються в тому ж порядку до LinkedHashMap
(який зберігає порядок ітерацій).
Коли виникає виняток, ExceptionHandlerExceptionResolver
воля перебирає їх ExceptionHandlerMethodResolver
і використовує перший, який може обробляти виняток.
Так точки тут: якщо у вас є @ControllerAdvice
з @ExceptionHandler
для Exception
що реєструються перед іншим @ControllerAdvice
класом з @ExceptionHandler
для більш конкретного винятку, як IOException
, що перші з них будуть викликатися. Як вже згадувалося раніше, ви можете керувати цим порядком реєстрації, @ControllerAdvice
реалізувавши свій анотований клас Ordered
або анотуючи його за допомогою @Order
або @Priority
і надаючи йому відповідне значення.
@ExceptionHandler
методів у межах a@ControllerAdvice
, вибирається той, який обробляє найбільш конкретний суперклас викинутого винятку.