Fallback to Object When Determining Overridden Methods

Closes gh-17898
This commit is contained in:
Josh Cummings 2025-09-15 09:16:50 -06:00
parent f844a9778b
commit f8272a8844
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
2 changed files with 33 additions and 1 deletions

View File

@ -308,7 +308,7 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
}
for (int i = 0; i < rootParameterTypes.length; i++) {
Class<?> resolvedParameterType = ResolvableType.forMethodParameter(candidateMethod, i, sourceDeclaringClass)
.resolve();
.toClass();
if (rootParameterTypes[i] != resolvedParameterType) {
return false;
}

View File

@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.core.annotation.AnnotationConfigurationException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -326,6 +327,14 @@ public class UniqueSecurityAnnotationScannerTests {
.isThrownBy(() -> this.parameterScanner.scan(parameter));
}
// gh-17898
@Test
void scanWhenAnnotationOnParameterizedUndeclaredMethodAndThenLocates() throws Exception {
Method method = ClassUtils.getMethod(GenericInterfaceImpl.class, "processOneAndTwo", Long.class, Object.class);
PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass());
assertThat(pre).isNotNull();
}
interface UserService {
void add(@CustomParameterAnnotation("one") String user);
@ -764,4 +773,27 @@ public class UniqueSecurityAnnotationScannerTests {
}
interface GenericInterface<A, B> {
@PreAuthorize("hasAuthority('thirtythree')")
void processOneAndTwo(A value1, B value2);
}
abstract static class GenericAbstractSuperclass<C> implements GenericInterface<Long, C> {
@Override
public void processOneAndTwo(Long value1, C value2) {
}
}
static class GenericInterfaceImpl extends GenericAbstractSuperclass<String> {
// The compiler does not require us to declare a concrete
// processOneAndTwo(Long, String) method, and we intentionally
// do not declare one here.
}
}