Related polishing

Issue. SPR-11428
(cherry picked from commit 9c6df76)
This commit is contained in:
Juergen Hoeller
2014-02-14 21:38:44 +01:00
parent bb7a1372c0
commit 5da79ebca6
15 changed files with 198 additions and 197 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@@ -37,9 +37,8 @@ import org.springframework.util.ReflectionUtils.MethodFilter;
public abstract class HandlerMethodSelector {
/**
* Selects handler methods for the given handler type. Callers of this method define handler methods
* of interest through the {@link MethodFilter} parameter.
*
* Select handler methods for the given handler type.
* <p>Callers define handler methods of interest through the {@link MethodFilter} parameter.
* @param handlerType the handler type to search handler methods on
* @param handlerMethodFilter a {@link MethodFilter} to help recognize handler methods of interest
* @return the selected methods, or an empty set

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@@ -43,14 +43,25 @@ import org.springframework.web.method.HandlerMethodSelector;
*/
public class ExceptionHandlerMethodResolver {
/**
* A filter for selecting {@code @ExceptionHandler} methods.
*/
public final static MethodFilter EXCEPTION_HANDLER_METHODS = new MethodFilter() {
public boolean matches(Method method) {
return (AnnotationUtils.findAnnotation(method, ExceptionHandler.class) != null);
}
};
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis");
private final Map<Class<? extends Throwable>, Method> mappedMethods =
new ConcurrentHashMap<Class<? extends Throwable>, Method>(16);
private final Map<Class<? extends Throwable>, Method> exceptionLookupCache =
new ConcurrentHashMap<Class<? extends Throwable>, Method>(16);
/**
* A constructor that finds {@link ExceptionHandler} methods in the given type.
* @param handlerType the type to introspect
@@ -63,6 +74,7 @@ public class ExceptionHandlerMethodResolver {
}
}
/**
* Extract exception mappings from the {@code @ExceptionHandler} annotation
* first and as a fall-back from the method signature.
@@ -70,10 +82,7 @@ public class ExceptionHandlerMethodResolver {
@SuppressWarnings("unchecked")
private List<Class<? extends Throwable>> detectExceptionMappings(Method method) {
List<Class<? extends Throwable>> result = new ArrayList<Class<? extends Throwable>>();
ExceptionHandler annotation = AnnotationUtils.findAnnotation(method, ExceptionHandler.class);
result.addAll(Arrays.asList(annotation.value()));
detectAnnotationExceptionMappings(method, result);
if (result.isEmpty()) {
for (Class<?> paramType : method.getParameterTypes()) {
if (Throwable.class.isAssignableFrom(paramType)) {
@@ -81,12 +90,15 @@ public class ExceptionHandlerMethodResolver {
}
}
}
Assert.notEmpty(result, "No exception types mapped to {" + method + "}");
return result;
}
protected void detectAnnotationExceptionMappings(Method method, List<Class<? extends Throwable>> result) {
ExceptionHandler annot = AnnotationUtils.findAnnotation(method, ExceptionHandler.class);
result.addAll(Arrays.asList(annot.value()));
}
private void addExceptionMapping(Class<? extends Throwable> exceptionType, Method method) {
Method oldMethod = this.mappedMethods.put(exceptionType, method);
if (oldMethod != null && !oldMethod.equals(method)) {
@@ -110,7 +122,16 @@ public class ExceptionHandlerMethodResolver {
* @return a method to handle the exception or {@code null}
*/
public Method resolveMethod(Exception exception) {
Class<? extends Exception> exceptionType = exception.getClass();
return resolveMethodByExceptionType(exception.getClass());
}
/**
* Find a method to handle the given exception type. This can be useful if
* an Exception instance is not available (example for tools).
* @param exceptionType the exception type
* @return a method to handle the exception or {@code null}
*/
public Method resolveMethodByExceptionType(Class<? extends Exception> exceptionType) {
Method method = this.exceptionLookupCache.get(exceptionType);
if (method == null) {
method = getMappedMethod(exceptionType);
@@ -131,21 +152,11 @@ public class ExceptionHandlerMethodResolver {
}
if (!matches.isEmpty()) {
Collections.sort(matches, new ExceptionDepthComparator(exceptionType));
return mappedMethods.get(matches.get(0));
return this.mappedMethods.get(matches.get(0));
}
else {
return null;
}
}
/**
* A filter for selecting {@code @ExceptionHandler} methods.
*/
public final static MethodFilter EXCEPTION_HANDLER_METHODS = new MethodFilter() {
public boolean matches(Method method) {
return AnnotationUtils.findAnnotation(method, ExceptionHandler.class) != null;
}
};
}