Skip to content

Commit da68781

Browse files
committed
Add support for records in BindingReflectionHintsRegistrar
Closes gh-28721
1 parent 89a6101 commit da68781

File tree

2 files changed

+52
-12
lines changed

2 files changed

+52
-12
lines changed

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

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.beans.Introspector;
2222
import java.beans.PropertyDescriptor;
2323
import java.lang.reflect.Method;
24+
import java.lang.reflect.RecordComponent;
2425
import java.lang.reflect.Type;
2526
import java.util.LinkedHashSet;
2627
import java.util.Set;
@@ -90,20 +91,28 @@ private void registerReflectionHints(ReflectionHints hints, Set<Type> seen, Type
9091
}
9192
seen.add(type);
9293
if (shouldRegisterMembers(clazz)) {
93-
builder.withMembers(
94-
MemberCategory.DECLARED_FIELDS,
95-
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
96-
try {
97-
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
98-
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
99-
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
100-
registerPropertyHints(hints, seen, propertyDescriptor.getWriteMethod(), 0);
101-
registerPropertyHints(hints, seen, propertyDescriptor.getReadMethod(), -1);
94+
if (clazz.isRecord()) {
95+
builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
96+
for (RecordComponent recordComponent : clazz.getRecordComponents()) {
97+
registerRecordHints(hints, seen, recordComponent.getAccessor());
10298
}
10399
}
104-
catch (IntrospectionException ex) {
105-
if (logger.isDebugEnabled()) {
106-
logger.debug("Ignoring referenced type [" + clazz.getName() + "]: " + ex.getMessage());
100+
else {
101+
builder.withMembers(
102+
MemberCategory.DECLARED_FIELDS,
103+
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
104+
try {
105+
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
106+
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
107+
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
108+
registerPropertyHints(hints, seen, propertyDescriptor.getWriteMethod(), 0);
109+
registerPropertyHints(hints, seen, propertyDescriptor.getReadMethod(), -1);
110+
}
111+
}
112+
catch (IntrospectionException ex) {
113+
if (logger.isDebugEnabled()) {
114+
logger.debug("Ignoring referenced type [" + clazz.getName() + "]: " + ex.getMessage());
115+
}
107116
}
108117
}
109118
}
@@ -115,6 +124,15 @@ private void registerReflectionHints(ReflectionHints hints, Set<Type> seen, Type
115124
referencedTypes.forEach(referencedType -> registerReflectionHints(hints, seen, referencedType));
116125
}
117126

127+
private void registerRecordHints(ReflectionHints hints, Set<Type> seen, Method method) {
128+
hints.registerMethod(method, INVOKE);
129+
MethodParameter methodParameter = MethodParameter.forExecutable(method, -1);
130+
Type methodParameterType = methodParameter.getGenericParameterType();
131+
if (!seen.contains(methodParameterType)) {
132+
registerReflectionHints(hints, seen, methodParameterType);
133+
}
134+
}
135+
118136
private void registerPropertyHints(ReflectionHints hints, Set<Type> seen, @Nullable Method method, int parameterIndex) {
119137
if (method != null && method.getDeclaringClass() != Object.class
120138
&& method.getDeclaringClass() != Enum.class) {

spring-core/src/test/java/org/springframework/aot/hint/support/BindingReflectionHintsRegistrarTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,26 @@ void registerTypeForSerializationWithEnum() {
203203
.satisfies(typeHint -> assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleEnum.class)));
204204
}
205205

206+
@Test
207+
void registerTypeForSerializationWithRecord() {
208+
bindingRegistrar.registerReflectionHints(this.hints.reflection(), SampleRecord.class);
209+
assertThat(this.hints.reflection().typeHints()).satisfiesExactlyInAnyOrder(
210+
typeHint -> {
211+
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(String.class));
212+
assertThat(typeHint.getMemberCategories()).isEmpty();
213+
assertThat(typeHint.constructors()).isEmpty();
214+
assertThat(typeHint.fields()).isEmpty();
215+
assertThat(typeHint.methods()).isEmpty();
216+
},
217+
typeHint -> {
218+
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleRecord.class));
219+
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
220+
assertThat(methodHint.getName()).isEqualTo("name");
221+
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
222+
});
223+
});
224+
}
225+
206226

207227
static class SampleEmptyClass {
208228
}
@@ -285,4 +305,6 @@ enum SampleEnum {
285305
value1, value2
286306
}
287307

308+
record SampleRecord(String name) {}
309+
288310
}

0 commit comments

Comments
 (0)