|
@@ -20,8 +20,10 @@ import java.lang.annotation.Annotation;
|
|
|
import java.lang.reflect.AnnotatedElement;
|
|
|
import java.lang.reflect.Executable;
|
|
|
import java.lang.reflect.Method;
|
|
|
+import java.lang.reflect.Modifier;
|
|
|
import java.lang.reflect.Parameter;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.List;
|
|
@@ -30,6 +32,7 @@ import java.util.Set;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
import org.springframework.core.MethodClassKey;
|
|
|
+import org.springframework.core.ResolvableType;
|
|
|
import org.springframework.core.annotation.AnnotationConfigurationException;
|
|
|
import org.springframework.core.annotation.MergedAnnotation;
|
|
|
import org.springframework.core.annotation.MergedAnnotations;
|
|
@@ -221,18 +224,15 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
|
|
|
return Collections.emptyList();
|
|
|
}
|
|
|
classesToSkip.add(targetClass);
|
|
|
- try {
|
|
|
- Method methodToUse = targetClass.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
|
|
+ Method methodToUse = findMethod(method, targetClass);
|
|
|
+ if (methodToUse != null) {
|
|
|
List<MergedAnnotation<A>> annotations = findDirectAnnotations(methodToUse);
|
|
|
if (!annotations.isEmpty()) {
|
|
|
return annotations;
|
|
|
}
|
|
|
}
|
|
|
- catch (NoSuchMethodException ex) {
|
|
|
- // move on
|
|
|
- }
|
|
|
- List<MergedAnnotation<A>> annotations = new ArrayList<>();
|
|
|
- annotations.addAll(findClosestMethodAnnotations(method, targetClass.getSuperclass(), classesToSkip));
|
|
|
+ List<MergedAnnotation<A>> annotations = new ArrayList<>(
|
|
|
+ findClosestMethodAnnotations(method, targetClass.getSuperclass(), classesToSkip));
|
|
|
for (Class<?> inter : targetClass.getInterfaces()) {
|
|
|
annotations.addAll(findClosestMethodAnnotations(method, inter, classesToSkip));
|
|
|
}
|
|
@@ -264,4 +264,52 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
|
|
|
.toList();
|
|
|
}
|
|
|
|
|
|
+ private static Method findMethod(Method method, Class<?> targetClass) {
|
|
|
+ for (Method candidate : targetClass.getDeclaredMethods()) {
|
|
|
+ if (candidate == method) {
|
|
|
+ return candidate;
|
|
|
+ }
|
|
|
+ if (isOverride(method, candidate)) {
|
|
|
+ return candidate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean isOverride(Method rootMethod, Method candidateMethod) {
|
|
|
+ return (!Modifier.isPrivate(candidateMethod.getModifiers())
|
|
|
+ && candidateMethod.getName().equals(rootMethod.getName())
|
|
|
+ && hasSameParameterTypes(rootMethod, candidateMethod));
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean hasSameParameterTypes(Method rootMethod, Method candidateMethod) {
|
|
|
+ if (candidateMethod.getParameterCount() != rootMethod.getParameterCount()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ Class<?>[] rootParameterTypes = rootMethod.getParameterTypes();
|
|
|
+ Class<?>[] candidateParameterTypes = candidateMethod.getParameterTypes();
|
|
|
+ if (Arrays.equals(candidateParameterTypes, rootParameterTypes)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return hasSameGenericTypeParameters(rootMethod, candidateMethod, rootParameterTypes);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean hasSameGenericTypeParameters(Method rootMethod, Method candidateMethod,
|
|
|
+ Class<?>[] rootParameterTypes) {
|
|
|
+
|
|
|
+ Class<?> sourceDeclaringClass = rootMethod.getDeclaringClass();
|
|
|
+ Class<?> candidateDeclaringClass = candidateMethod.getDeclaringClass();
|
|
|
+ if (!candidateDeclaringClass.isAssignableFrom(sourceDeclaringClass)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ for (int i = 0; i < rootParameterTypes.length; i++) {
|
|
|
+ Class<?> resolvedParameterType = ResolvableType.forMethodParameter(candidateMethod, i, sourceDeclaringClass)
|
|
|
+ .resolve();
|
|
|
+ if (rootParameterTypes[i] != resolvedParameterType) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
}
|