Add support for records in BindingReflectionHintsRegistrar

Closes gh-28721
This commit is contained in:
Sébastien Deleuze 2022-06-30 11:43:16 +02:00
parent 89a6101b2e
commit da68781b9e
2 changed files with 52 additions and 12 deletions

View File

@ -21,6 +21,7 @@ import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.RecordComponent;
import java.lang.reflect.Type;
import java.util.LinkedHashSet;
import java.util.Set;
@ -90,20 +91,28 @@ public class BindingReflectionHintsRegistrar {
}
seen.add(type);
if (shouldRegisterMembers(clazz)) {
builder.withMembers(
MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
try {
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
registerPropertyHints(hints, seen, propertyDescriptor.getWriteMethod(), 0);
registerPropertyHints(hints, seen, propertyDescriptor.getReadMethod(), -1);
if (clazz.isRecord()) {
builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
for (RecordComponent recordComponent : clazz.getRecordComponents()) {
registerRecordHints(hints, seen, recordComponent.getAccessor());
}
}
catch (IntrospectionException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring referenced type [" + clazz.getName() + "]: " + ex.getMessage());
else {
builder.withMembers(
MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
try {
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
registerPropertyHints(hints, seen, propertyDescriptor.getWriteMethod(), 0);
registerPropertyHints(hints, seen, propertyDescriptor.getReadMethod(), -1);
}
}
catch (IntrospectionException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring referenced type [" + clazz.getName() + "]: " + ex.getMessage());
}
}
}
}
@ -115,6 +124,15 @@ public class BindingReflectionHintsRegistrar {
referencedTypes.forEach(referencedType -> registerReflectionHints(hints, seen, referencedType));
}
private void registerRecordHints(ReflectionHints hints, Set<Type> seen, Method method) {
hints.registerMethod(method, INVOKE);
MethodParameter methodParameter = MethodParameter.forExecutable(method, -1);
Type methodParameterType = methodParameter.getGenericParameterType();
if (!seen.contains(methodParameterType)) {
registerReflectionHints(hints, seen, methodParameterType);
}
}
private void registerPropertyHints(ReflectionHints hints, Set<Type> seen, @Nullable Method method, int parameterIndex) {
if (method != null && method.getDeclaringClass() != Object.class
&& method.getDeclaringClass() != Enum.class) {

View File

@ -203,6 +203,26 @@ public class BindingReflectionHintsRegistrarTests {
.satisfies(typeHint -> assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleEnum.class)));
}
@Test
void registerTypeForSerializationWithRecord() {
bindingRegistrar.registerReflectionHints(this.hints.reflection(), SampleRecord.class);
assertThat(this.hints.reflection().typeHints()).satisfiesExactlyInAnyOrder(
typeHint -> {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(String.class));
assertThat(typeHint.getMemberCategories()).isEmpty();
assertThat(typeHint.constructors()).isEmpty();
assertThat(typeHint.fields()).isEmpty();
assertThat(typeHint.methods()).isEmpty();
},
typeHint -> {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleRecord.class));
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
assertThat(methodHint.getName()).isEqualTo("name");
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
});
});
}
static class SampleEmptyClass {
}
@ -285,4 +305,6 @@ public class BindingReflectionHintsRegistrarTests {
value1, value2
}
record SampleRecord(String name) {}
}