Polishing.

Introduce common exclusion rules for constructors.

See: #2744
Original pull request: #2746
This commit is contained in:
Mark Paluch
2022-12-12 16:47:33 +01:00
parent 1d7c1ff6e0
commit 4c2b8ac4c8
2 changed files with 56 additions and 22 deletions

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -30,22 +31,24 @@ import org.springframework.util.Assert;
*/
public interface Predicates {
public static final Predicate<Member> IS_ENUM_MEMBER = member -> member.getDeclaringClass().isEnum();
public static final Predicate<Member> IS_HIBERNATE_MEMBER = member -> member.getName().startsWith("$$_hibernate"); // this
Predicate<Member> IS_ENUM_MEMBER = member -> member.getDeclaringClass().isEnum();
Predicate<Member> IS_HIBERNATE_MEMBER = member -> member.getName().startsWith("$$_hibernate"); // this
// should
// go
// into
// JPA
public static final Predicate<Member> IS_OBJECT_MEMBER = member -> Object.class.equals(member.getDeclaringClass());
public static final Predicate<Member> IS_JAVA = member -> member.getDeclaringClass().getPackageName().startsWith("java.");
public static final Predicate<Member> IS_NATIVE = member -> Modifier.isNative(member.getModifiers());
public static final Predicate<Member> IS_PRIVATE = member -> Modifier.isPrivate(member.getModifiers());
public static final Predicate<Member> IS_PROTECTED = member -> Modifier.isProtected(member.getModifiers());
public static final Predicate<Member> IS_PUBLIC = member -> Modifier.isPublic(member.getModifiers());
public static final Predicate<Member> IS_SYNTHETIC = Member::isSynthetic;
public static final Predicate<Member> IS_STATIC = member -> Modifier.isStatic(member.getModifiers());
Predicate<Member> IS_OBJECT_MEMBER = member -> Object.class.equals(member.getDeclaringClass());
Predicate<Member> IS_JAVA = member -> member.getDeclaringClass().getPackageName().startsWith("java.");
Predicate<Member> IS_NATIVE = member -> Modifier.isNative(member.getModifiers());
Predicate<Member> IS_PRIVATE = member -> Modifier.isPrivate(member.getModifiers());
Predicate<Member> IS_PROTECTED = member -> Modifier.isProtected(member.getModifiers());
Predicate<Member> IS_PUBLIC = member -> Modifier.isPublic(member.getModifiers());
Predicate<Member> IS_SYNTHETIC = Member::isSynthetic;
public static final Predicate<Method> IS_BRIDGE_METHOD = Method::isBridge;
Predicate<Class<?>> IS_KOTLIN = KotlinReflectionUtils::isSupportedKotlinClass;
Predicate<Member> IS_STATIC = member -> Modifier.isStatic(member.getModifiers());
Predicate<Method> IS_BRIDGE_METHOD = Method::isBridge;
/**
* A {@link Predicate} that yields always {@code true}.
@@ -75,4 +78,29 @@ public interface Predicates {
Assert.notNull(predicate, "Predicate must not be null");
return predicate.negate();
}
/**
* Whether to consider a {@link Constructor}. We generally exclude synthetic constructors for non-Kotlin classes.
*
* @param candidate
* @return
*/
static boolean isIncluded(Constructor<?> candidate) {
return !isExcluded(candidate);
}
/**
* Whether to not consider a {@link Constructor}. We generally exclude synthetic constructors for non-Kotlin classes.
*
* @param candidate
* @return
*/
static boolean isExcluded(Constructor<?> candidate) {
if (IS_KOTLIN.test(candidate.getDeclaringClass())) {
return false;
}
return IS_SYNTHETIC.test(candidate);
}
}

View File

@@ -20,16 +20,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -40,9 +31,15 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
/**
* Collector to inspect domain types and discover the type graph that is relevant for Spring Data operations.
* <p>
* Type inspection walks through all class members (fields, methods, constructors) and introspects those for additional
* types that are part of the domain model.
*
* @author Christoph Strobl
* @author Sebastien Deleuze
* @author John Blum
* @since 3.0
*/
public class TypeCollector {
@@ -122,13 +119,16 @@ public class TypeCollector {
}
Set<Type> visitConstructorsOfType(ResolvableType type) {
if (!typeFilter.test(type.toClass())) {
return Collections.emptySet();
}
Set<Type> discoveredTypes = new LinkedHashSet<>();
for (Constructor<?> constructor : type.toClass().getDeclaredConstructors()) {
if (constructor.isSynthetic()) {
if (Predicates.isExcluded(constructor)) {
continue;
}
for (Class<?> signatureType : TypeUtils.resolveTypesInSignature(type.toClass(), constructor)) {
@@ -137,10 +137,12 @@ public class TypeCollector {
}
}
}
return new HashSet<>(discoveredTypes);
}
Set<Type> visitMethodsOfType(ResolvableType type) {
if (!typeFilter.test(type.toClass())) {
return Collections.emptySet();
}
@@ -160,11 +162,14 @@ public class TypeCollector {
} catch (Exception cause) {
logger.warn(cause);
}
return new HashSet<>(discoveredTypes);
}
Set<Type> visitFieldsOfType(ResolvableType type) {
Set<Type> discoveredTypes = new LinkedHashSet<>();
ReflectionUtils.doWithLocalFields(type.toClass(), field -> {
if (!fieldFilter.test(field)) {
return;
@@ -175,6 +180,7 @@ public class TypeCollector {
}
}
});
return discoveredTypes;
}