diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index 879cc78b6ac..9c2835de7ca 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -294,6 +294,7 @@ private void initMessageConverters() { this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(new StringHttpMessageConverter()); this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); + } private void initExceptionHandlerAdviceCache() { @@ -302,6 +303,17 @@ private void initExceptionHandlerAdviceCache() { } List adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); + adviceBeans.sort((bean1, bean2) -> { + boolean hasSelectors1 = hasSelectors(bean1); + boolean hasSelectors2 = hasSelectors(bean2); + if (hasSelectors1 && !hasSelectors2) { + return -1; + } else if (!hasSelectors1 && hasSelectors2) { + return 1; + } else { + return 0; + } + }); for (ControllerAdviceBean adviceBean : adviceBeans) { Class beanType = adviceBean.getBeanType(); if (beanType == null) { @@ -329,6 +341,21 @@ private void initExceptionHandlerAdviceCache() { } } + private boolean hasSelectors(ControllerAdviceBean adviceBean) { + Class beanType = adviceBean.getBeanType(); + if (beanType == null) { + return false; + } + ControllerAdvice controllerAdvice = AnnotationUtils.getAnnotation(beanType, ControllerAdvice.class); + if (controllerAdvice == null) { + return false; + } + + return (controllerAdvice.basePackages().length > 0) + || (controllerAdvice.assignableTypes().length > 0) + || (controllerAdvice.annotations().length > 0); + } + /** * Return an unmodifiable Map with the {@link ControllerAdvice @ControllerAdvice} * beans discovered in the ApplicationContext. The returned map will be empty if