diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractExceptionHandlerMethodResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractExceptionHandlerMethodResolver.java index 2173824c82..97c89b8fd6 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractExceptionHandlerMethodResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractExceptionHandlerMethodResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,6 +38,19 @@ import org.springframework.util.ConcurrentReferenceHashMap; */ public abstract class AbstractExceptionHandlerMethodResolver { + private static final Method NO_MATCHING_EXCEPTION_HANDLER_METHOD; + + static { + try { + NO_MATCHING_EXCEPTION_HANDLER_METHOD = + AbstractExceptionHandlerMethodResolver.class.getDeclaredMethod("noMatchingExceptionHandler"); + } + catch (NoSuchMethodException ex) { + throw new IllegalStateException("Expected method not found: " + ex); + } + } + + private final Map, Method> mappedMethods = new HashMap<>(16); private final Map, Method> exceptionLookupCache = new ConcurrentReferenceHashMap<>(16); @@ -110,7 +123,7 @@ public abstract class AbstractExceptionHandlerMethodResolver { method = getMappedMethod(exceptionType); this.exceptionLookupCache.put(exceptionType, method); } - return method; + return (method != NO_MATCHING_EXCEPTION_HANDLER_METHOD ? method : null); } /** @@ -129,8 +142,14 @@ public abstract class AbstractExceptionHandlerMethodResolver { return this.mappedMethods.get(matches.get(0)); } else { - return null; + return NO_MATCHING_EXCEPTION_HANDLER_METHOD; } } + /** + * For the NO_MATCHING_EXCEPTION_HANDLER_METHOD constant. + */ + private void noMatchingExceptionHandler() { + } + } diff --git a/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java b/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java index 5fc02bd9ed..697092bc3a 100644 --- a/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java +++ b/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,6 +49,18 @@ public class ExceptionHandlerMethodResolver { public static final MethodFilter EXCEPTION_HANDLER_METHODS = method -> AnnotatedElementUtils.hasAnnotation(method, ExceptionHandler.class); + private static final Method NO_MATCHING_EXCEPTION_HANDLER_METHOD; + + static { + try { + NO_MATCHING_EXCEPTION_HANDLER_METHOD = + ExceptionHandlerMethodResolver.class.getDeclaredMethod("noMatchingExceptionHandler"); + } + catch (NoSuchMethodException ex) { + throw new IllegalStateException("Expected method not found: " + ex); + } + } + private final Map, Method> mappedMethods = new HashMap<>(16); @@ -153,13 +165,12 @@ public class ExceptionHandlerMethodResolver { method = getMappedMethod(exceptionType); this.exceptionLookupCache.put(exceptionType, method); } - return method; + return (method != NO_MATCHING_EXCEPTION_HANDLER_METHOD ? method : null); } /** * Return the {@link Method} mapped to the given exception type, or {@code null} if none. */ - @Nullable private Method getMappedMethod(Class exceptionType) { List> matches = new ArrayList<>(); for (Class mappedException : this.mappedMethods.keySet()) { @@ -172,8 +183,14 @@ public class ExceptionHandlerMethodResolver { return this.mappedMethods.get(matches.get(0)); } else { - return null; + return NO_MATCHING_EXCEPTION_HANDLER_METHOD; } } + /** + * For the NO_MATCHING_EXCEPTION_HANDLER_METHOD constant. + */ + private void noMatchingExceptionHandler() { + } + }