From bbe285dd42763b1191ffe7b3e3ace758d30f9972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Fri, 7 Oct 2022 11:29:34 +0200 Subject: [PATCH] Polish RegisterReflectionForBinding support Implementation and Javadoc refinements. See gh-29279 --- .../hint/BindingReflectionHintsRegistrar.java | 32 +++++++------------ .../RegisterReflectionForBinding.java | 10 +++--- ...RegisterReflectionForBindingProcessor.java | 2 +- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java b/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java index 4c560eb91632..d2356de7dd03 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java @@ -39,8 +39,8 @@ * Register the necessary reflection hints so that the specified type can be * bound at runtime. Fields, constructors, properties and record components * are registered, except for a set of types like those in the {@code java.} - * package where just the type is registered. - * Types are discovered transitively and generic type are registered as well. + * package where just the type is registered. Types are discovered transitively + * on properties and record components, and generic types are registered as well. * * @author Sebastien Deleuze * @since 6.0 @@ -54,7 +54,7 @@ public class BindingReflectionHintsRegistrar { /** * Register the necessary reflection hints to bind the specified types. * @param hints the hints instance to use - * @param types the types to bind + * @param types the types to register */ public void registerReflectionHints(ReflectionHints hints, Type... types) { Set seen = new LinkedHashSet<>(); @@ -73,15 +73,15 @@ protected boolean shouldRegisterMembers(Class type) { } private void registerReflectionHints(ReflectionHints hints, Set seen, Type type) { + if (seen.contains(type)) { + return; + } + seen.add(type); if (type instanceof Class clazz) { if (clazz.isPrimitive() || clazz == Object.class) { return; } hints.registerType(clazz, typeHint -> { - if (seen.contains(type)) { - return; - } - seen.add(type); if (shouldRegisterMembers(clazz)) { if (clazz.isRecord()) { typeHint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); @@ -114,7 +114,7 @@ private void registerReflectionHints(ReflectionHints hints, Set seen, Type }); } Set> referencedTypes = new LinkedHashSet<>(); - collectReferencedTypes(seen, referencedTypes, type); + collectReferencedTypes(referencedTypes, ResolvableType.forType(type)); referencedTypes.forEach(referencedType -> registerReflectionHints(hints, seen, referencedType)); } @@ -122,9 +122,7 @@ private void registerRecordHints(ReflectionHints hints, Set seen, Method m hints.registerMethod(method, ExecutableMode.INVOKE); MethodParameter methodParameter = MethodParameter.forExecutable(method, -1); Type methodParameterType = methodParameter.getGenericParameterType(); - if (!seen.contains(methodParameterType)) { - registerReflectionHints(hints, seen, methodParameterType); - } + registerReflectionHints(hints, seen, methodParameterType); } private void registerPropertyHints(ReflectionHints hints, Set seen, @Nullable Method method, int parameterIndex) { @@ -133,9 +131,7 @@ private void registerPropertyHints(ReflectionHints hints, Set seen, @Nulla hints.registerMethod(method, ExecutableMode.INVOKE); MethodParameter methodParameter = MethodParameter.forExecutable(method, parameterIndex); Type methodParameterType = methodParameter.getGenericParameterType(); - if (!seen.contains(methodParameterType)) { - registerReflectionHints(hints, seen, methodParameterType); - } + registerReflectionHints(hints, seen, methodParameterType); } } @@ -150,16 +146,12 @@ private void registerKotlinSerializationHints(ReflectionHints hints, Class cl } } - private void collectReferencedTypes(Set seen, Set> types, Type type) { - if (seen.contains(type)) { - return; - } - ResolvableType resolvableType = ResolvableType.forType(type); + private void collectReferencedTypes(Set> types, ResolvableType resolvableType) { Class clazz = resolvableType.resolve(); if (clazz != null && !types.contains(clazz)) { types.add(clazz); for (ResolvableType genericResolvableType : resolvableType.getGenerics()) { - collectReferencedTypes(seen, types, genericResolvableType.getType()); + collectReferencedTypes(types, genericResolvableType); } } } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java b/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java index 37d86314a556..ff809c2d1498 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java @@ -26,8 +26,8 @@ /** * Indicates that one or more {@link Class} reflection hints should be registered for - * data binding purpose (class, fields, properties, record components for the whole - * type hierarchy). + * data binding purpose (class, fields, properties, record components, including + * types transitively used on properties and record components). * *

Typically used to annotate the bean class or bean method where the reflection hint * is needed. @@ -42,16 +42,14 @@ public @interface RegisterReflectionForBinding { /** - * Classes for which reflection hints should be registered to enable data binding - * (class, fields, properties, record components for the whole type hierarchy). + * Classes for which reflection hints should be registered. * @see #classes() */ @AliasFor("classes") Class[] value() default {}; /** - * Classes for which reflection hints should be registered to enable data binding - * (class, fields, properties, record components for the whole type hierarchy). + * Classes for which reflection hints should be registered. * @see #value() */ @AliasFor("value") diff --git a/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessor.java b/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessor.java index b92e1549ba8e..6fb94cc3d4a7 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessor.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessor.java @@ -25,7 +25,7 @@ /** * A {@link ReflectiveProcessor} implementation that registers reflection hints * for data binding purpose (class, constructors, fields, properties, record - * components for the whole type hierarchy). + * components, including types transitively used on properties and record components). * * @author Sebastien Deleuze * @since 6.0