Merge branch '5.3.x'
This commit is contained in:
commit
08daacfc1b
|
@ -46,12 +46,12 @@ import org.springframework.lang.Nullable;
|
|||
public abstract class ReflectionUtils {
|
||||
|
||||
/**
|
||||
* Pre-built MethodFilter that matches all non-bridge non-synthetic methods
|
||||
* Pre-built {@link MethodFilter} that matches all non-bridge non-synthetic methods
|
||||
* which are not declared on {@code java.lang.Object}.
|
||||
* @since 3.0.5
|
||||
*/
|
||||
public static final MethodFilter USER_DECLARED_METHODS =
|
||||
(method -> !method.isBridge() && !method.isSynthetic());
|
||||
(method -> !method.isBridge() && !method.isSynthetic() && (method.getDeclaringClass() != Object.class));
|
||||
|
||||
/**
|
||||
* Pre-built FieldFilter that matches all non-static, non-final fields.
|
||||
|
@ -353,7 +353,10 @@ public abstract class ReflectionUtils {
|
|||
* @throws IllegalStateException if introspection fails
|
||||
*/
|
||||
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
|
||||
// Keep backing up the inheritance hierarchy.
|
||||
if (mf == USER_DECLARED_METHODS && clazz == Object.class) {
|
||||
// nothing to introspect
|
||||
return;
|
||||
}
|
||||
Method[] methods = getDeclaredMethods(clazz, false);
|
||||
for (Method method : methods) {
|
||||
if (mf != null && !mf.matches(method)) {
|
||||
|
@ -366,6 +369,7 @@ public abstract class ReflectionUtils {
|
|||
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
|
||||
}
|
||||
}
|
||||
// Keep backing up the inheritance hierarchy.
|
||||
if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
|
||||
doWithMethods(clazz.getSuperclass(), mc, mf);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
|
@ -28,6 +28,7 @@ import org.junit.jupiter.api.Disabled;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.tests.sample.objects.TestObject;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
@ -184,27 +185,46 @@ class ReflectionUtilsTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void doWithProtectedMethods() {
|
||||
void doWithMethodsUsingProtectedFilter() {
|
||||
ListSavingMethodCallback mc = new ListSavingMethodCallback();
|
||||
ReflectionUtils.doWithMethods(TestObject.class, mc, method -> Modifier.isProtected(method.getModifiers()));
|
||||
assertThat(mc.getMethodNames().isEmpty()).isFalse();
|
||||
assertThat(mc.getMethodNames().contains("clone")).as("Must find protected method on Object").isTrue();
|
||||
assertThat(mc.getMethodNames().contains("finalize")).as("Must find protected method on Object").isTrue();
|
||||
assertThat(mc.getMethodNames().contains("hashCode")).as("Public, not protected").isFalse();
|
||||
assertThat(mc.getMethodNames().contains("absquatulate")).as("Public, not protected").isFalse();
|
||||
assertThat(mc.getMethodNames())
|
||||
.hasSizeGreaterThanOrEqualTo(2)
|
||||
.as("Must find protected methods on Object").contains("clone", "finalize")
|
||||
.as("Public, not protected").doesNotContain("hashCode", "absquatulate");
|
||||
}
|
||||
|
||||
@Test
|
||||
void duplicatesFound() {
|
||||
void doWithMethodsUsingUserDeclaredMethodsFilterStartingWithObject() {
|
||||
ListSavingMethodCallback mc = new ListSavingMethodCallback();
|
||||
ReflectionUtils.doWithMethods(Object.class, mc, ReflectionUtils.USER_DECLARED_METHODS);
|
||||
assertThat(mc.getMethodNames()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doWithMethodsUsingUserDeclaredMethodsFilterStartingWithTestObject() {
|
||||
ListSavingMethodCallback mc = new ListSavingMethodCallback();
|
||||
ReflectionUtils.doWithMethods(TestObject.class, mc, ReflectionUtils.USER_DECLARED_METHODS);
|
||||
assertThat(mc.getMethodNames())
|
||||
.as("user declared methods").contains("absquatulate", "compareTo", "getName", "setName", "getAge", "setAge", "getSpouse", "setSpouse")
|
||||
.as("methods on Object").doesNotContain("equals", "hashCode", "toString", "clone", "finalize", "getClass", "notify", "notifyAll", "wait");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doWithMethodsUsingUserDeclaredMethodsComposedFilter() {
|
||||
ListSavingMethodCallback mc = new ListSavingMethodCallback();
|
||||
// "q" because both absquatulate() and equals() contain "q"
|
||||
MethodFilter isSetterMethodOrNameContainsQ = m -> m.getName().startsWith("set") || m.getName().contains("q");
|
||||
MethodFilter methodFilter = ReflectionUtils.USER_DECLARED_METHODS.and(isSetterMethodOrNameContainsQ);
|
||||
ReflectionUtils.doWithMethods(TestObject.class, mc, methodFilter);
|
||||
assertThat(mc.getMethodNames()).containsExactlyInAnyOrder("setName", "setAge", "setSpouse", "absquatulate");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doWithMethodsFindsDuplicatesInClassHierarchy() {
|
||||
ListSavingMethodCallback mc = new ListSavingMethodCallback();
|
||||
ReflectionUtils.doWithMethods(TestObjectSubclass.class, mc);
|
||||
int absquatulateCount = 0;
|
||||
for (String name : mc.getMethodNames()) {
|
||||
if (name.equals("absquatulate")) {
|
||||
++absquatulateCount;
|
||||
}
|
||||
}
|
||||
assertThat(absquatulateCount).as("Found 2 absquatulates").isEqualTo(2);
|
||||
assertThat(mc.getMethodNames().stream()).filteredOn("absquatulate"::equals).as("Found 2 absquatulates").hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue