Skip to content

Commit 6446ffd

Browse files
committed
BridgeMethodResolver properly resolves interface hierarchies
Issue: SPR-16103 (cherry picked from commit 182da15)
1 parent db7d715 commit 6446ffd

File tree

2 files changed

+166
-95
lines changed

2 files changed

+166
-95
lines changed

spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -59,6 +59,7 @@ public static Method findBridgedMethod(Method bridgeMethod) {
5959
if (bridgeMethod == null || !bridgeMethod.isBridge()) {
6060
return bridgeMethod;
6161
}
62+
6263
// Gather all methods with matching name and parameter size.
6364
List<Method> candidateMethods = new ArrayList<Method>();
6465
Method[] methods = ReflectionUtils.getAllDeclaredMethods(bridgeMethod.getDeclaringClass());
@@ -67,10 +68,12 @@ public static Method findBridgedMethod(Method bridgeMethod) {
6768
candidateMethods.add(candidateMethod);
6869
}
6970
}
71+
7072
// Now perform simple quick check.
7173
if (candidateMethods.size() == 1) {
7274
return candidateMethods.get(0);
7375
}
76+
7477
// Search for candidate match.
7578
Method bridgedMethod = searchCandidates(candidateMethods, bridgeMethod);
7679
if (bridgedMethod != null) {
@@ -133,42 +136,13 @@ static boolean isBridgeMethodFor(Method bridgeMethod, Method candidateMethod, Cl
133136
return (method != null && isResolvedTypeMatch(method, candidateMethod, declaringClass));
134137
}
135138

136-
/**
137-
* Searches for the generic {@link Method} declaration whose erased signature
138-
* matches that of the supplied bridge method.
139-
* @throws IllegalStateException if the generic declaration cannot be found
140-
*/
141-
private static Method findGenericDeclaration(Method bridgeMethod) {
142-
// Search parent types for method that has same signature as bridge.
143-
Class<?> superclass = bridgeMethod.getDeclaringClass().getSuperclass();
144-
while (superclass != null && Object.class != superclass) {
145-
Method method = searchForMatch(superclass, bridgeMethod);
146-
if (method != null && !method.isBridge()) {
147-
return method;
148-
}
149-
superclass = superclass.getSuperclass();
150-
}
151-
152-
// Search interfaces.
153-
Class<?>[] interfaces = ClassUtils.getAllInterfacesForClass(bridgeMethod.getDeclaringClass());
154-
for (Class<?> ifc : interfaces) {
155-
Method method = searchForMatch(ifc, bridgeMethod);
156-
if (method != null && !method.isBridge()) {
157-
return method;
158-
}
159-
}
160-
161-
return null;
162-
}
163-
164139
/**
165140
* Returns {@code true} if the {@link Type} signature of both the supplied
166141
* {@link Method#getGenericParameterTypes() generic Method} and concrete {@link Method}
167142
* are equal after resolving all types against the declaringType, otherwise
168143
* returns {@code false}.
169144
*/
170-
private static boolean isResolvedTypeMatch(
171-
Method genericMethod, Method candidateMethod, Class<?> declaringClass) {
145+
private static boolean isResolvedTypeMatch(Method genericMethod, Method candidateMethod, Class<?> declaringClass) {
172146
Type[] genericParameters = genericMethod.getGenericParameterTypes();
173147
Class<?>[] candidateParameters = candidateMethod.getParameterTypes();
174148
if (genericParameters.length != candidateParameters.length) {
@@ -191,13 +165,51 @@ private static boolean isResolvedTypeMatch(
191165
return true;
192166
}
193167

168+
/**
169+
* Searches for the generic {@link Method} declaration whose erased signature
170+
* matches that of the supplied bridge method.
171+
* @throws IllegalStateException if the generic declaration cannot be found
172+
*/
173+
private static Method findGenericDeclaration(Method bridgeMethod) {
174+
// Search parent types for method that has same signature as bridge.
175+
Class<?> superclass = bridgeMethod.getDeclaringClass().getSuperclass();
176+
while (superclass != null && Object.class != superclass) {
177+
Method method = searchForMatch(superclass, bridgeMethod);
178+
if (method != null && !method.isBridge()) {
179+
return method;
180+
}
181+
superclass = superclass.getSuperclass();
182+
}
183+
184+
Class<?>[] interfaces = ClassUtils.getAllInterfacesForClass(bridgeMethod.getDeclaringClass());
185+
return searchInterfaces(interfaces, bridgeMethod);
186+
}
187+
188+
private static Method searchInterfaces(Class<?>[] interfaces, Method bridgeMethod) {
189+
for (Class<?> ifc : interfaces) {
190+
Method method = searchForMatch(ifc, bridgeMethod);
191+
if (method != null && !method.isBridge()) {
192+
return method;
193+
}
194+
else {
195+
return searchInterfaces(ifc.getInterfaces(), bridgeMethod);
196+
}
197+
}
198+
return null;
199+
}
200+
194201
/**
195202
* If the supplied {@link Class} has a declared {@link Method} whose signature matches
196203
* that of the supplied {@link Method}, then this matching {@link Method} is returned,
197204
* otherwise {@code null} is returned.
198205
*/
199206
private static Method searchForMatch(Class<?> type, Method bridgeMethod) {
200-
return ReflectionUtils.findMethod(type, bridgeMethod.getName(), bridgeMethod.getParameterTypes());
207+
try {
208+
return type.getDeclaredMethod(bridgeMethod.getName(), bridgeMethod.getParameterTypes());
209+
}
210+
catch (NoSuchMethodException ex) {
211+
return null;
212+
}
201213
}
202214

203215
/**

0 commit comments

Comments
 (0)