Browse Source

Polish RegisterReflectionForBinding support

Implementation and Javadoc refinements.

See gh-29279
pull/29282/head
Sébastien Deleuze 4 years ago
parent
commit
bbe285dd42
  1. 32
      spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java
  2. 10
      spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java
  3. 2
      spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessor.java

32
spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java

@ -39,8 +39,8 @@ import org.springframework.util.ClassUtils; @@ -39,8 +39,8 @@ import org.springframework.util.ClassUtils;
* 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 { @@ -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<Type> seen = new LinkedHashSet<>();
@ -73,15 +73,15 @@ public class BindingReflectionHintsRegistrar { @@ -73,15 +73,15 @@ public class BindingReflectionHintsRegistrar {
}
private void registerReflectionHints(ReflectionHints hints, Set<Type> 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 @@ public class BindingReflectionHintsRegistrar { @@ -114,7 +114,7 @@ public class BindingReflectionHintsRegistrar {
});
}
Set<Class<?>> referencedTypes = new LinkedHashSet<>();
collectReferencedTypes(seen, referencedTypes, type);
collectReferencedTypes(referencedTypes, ResolvableType.forType(type));
referencedTypes.forEach(referencedType -> registerReflectionHints(hints, seen, referencedType));
}
@ -122,9 +122,7 @@ public class BindingReflectionHintsRegistrar { @@ -122,9 +122,7 @@ public class BindingReflectionHintsRegistrar {
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<Type> seen, @Nullable Method method, int parameterIndex) {
@ -133,9 +131,7 @@ public class BindingReflectionHintsRegistrar { @@ -133,9 +131,7 @@ public class BindingReflectionHintsRegistrar {
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 @@ public class BindingReflectionHintsRegistrar { @@ -150,16 +146,12 @@ public class BindingReflectionHintsRegistrar {
}
}
private void collectReferencedTypes(Set<Type> seen, Set<Class<?>> types, Type type) {
if (seen.contains(type)) {
return;
}
ResolvableType resolvableType = ResolvableType.forType(type);
private void collectReferencedTypes(Set<Class<?>> 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);
}
}
}

10
spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java

@ -26,8 +26,8 @@ import org.springframework.core.annotation.AliasFor; @@ -26,8 +26,8 @@ import org.springframework.core.annotation.AliasFor;
/**
* 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).
*
* <p>Typically used to annotate the bean class or bean method where the reflection hint
* is needed.
@ -42,16 +42,14 @@ import org.springframework.core.annotation.AliasFor; @@ -42,16 +42,14 @@ import org.springframework.core.annotation.AliasFor;
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")

2
spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessor.java

@ -25,7 +25,7 @@ import org.springframework.core.annotation.AnnotationUtils; @@ -25,7 +25,7 @@ import org.springframework.core.annotation.AnnotationUtils;
/**
* 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

Loading…
Cancel
Save