22
22
import java .beans .PropertyDescriptor ;
23
23
import java .lang .reflect .Method ;
24
24
import java .lang .reflect .Type ;
25
- import java .util .HashSet ;
26
25
import java .util .LinkedHashSet ;
27
26
import java .util .Set ;
28
27
import java .util .function .Consumer ;
34
33
import org .springframework .aot .hint .ExecutableMode ;
35
34
import org .springframework .aot .hint .MemberCategory ;
36
35
import org .springframework .aot .hint .ReflectionHints ;
37
- import org .springframework .aot .hint .TypeHint .Builder ;
38
36
import org .springframework .core .KotlinDetector ;
39
37
import org .springframework .core .MethodParameter ;
40
38
import org .springframework .core .ResolvableType ;
@@ -66,16 +64,9 @@ public class BindingReflectionHintsRegistrar {
66
64
* @param types the types to bind
67
65
*/
68
66
public void registerReflectionHints (ReflectionHints hints , Type ... types ) {
67
+ Set <Type > seen = new LinkedHashSet <>();
69
68
for (Type type : types ) {
70
- Set <Class <?>> referencedTypes = new LinkedHashSet <>();
71
- collectReferencedTypes (new HashSet <>(), referencedTypes , type );
72
- for (Class <?> referencedType : referencedTypes ) {
73
- hints .registerType (referencedType , builder -> {
74
- if (shouldRegisterMembers (referencedType )) {
75
- registerMembers (hints , referencedType , builder );
76
- }
77
- });
78
- }
69
+ registerReflectionHints (hints , seen , type );
79
70
}
80
71
}
81
72
@@ -88,40 +79,60 @@ protected boolean shouldRegisterMembers(Class<?> type) {
88
79
return !type .getCanonicalName ().startsWith ("java." );
89
80
}
90
81
91
- private void registerMembers (ReflectionHints hints , Class <?> type , Builder builder ) {
92
- builder .withMembers (MemberCategory .DECLARED_FIELDS ,
93
- MemberCategory .INVOKE_DECLARED_CONSTRUCTORS );
94
- try {
95
- BeanInfo beanInfo = Introspector .getBeanInfo (type );
96
- PropertyDescriptor [] propertyDescriptors = beanInfo .getPropertyDescriptors ();
97
- for (PropertyDescriptor propertyDescriptor : propertyDescriptors ) {
98
- Method writeMethod = propertyDescriptor .getWriteMethod ();
99
- if (writeMethod != null && writeMethod .getDeclaringClass () != Object .class ) {
100
- hints .registerMethod (writeMethod , INVOKE );
101
- MethodParameter methodParameter = MethodParameter .forExecutable (writeMethod , 0 );
102
- registerReflectionHints (hints , methodParameter .getGenericParameterType ());
103
- }
104
- Method readMethod = propertyDescriptor .getReadMethod ();
105
- if (readMethod != null && readMethod .getDeclaringClass () != Object .class ) {
106
- hints .registerMethod (readMethod , INVOKE );
107
- MethodParameter methodParameter = MethodParameter .forExecutable (readMethod , -1 );
108
- registerReflectionHints (hints , methodParameter .getGenericParameterType ());
82
+ private void registerReflectionHints (ReflectionHints hints , Set <Type > seen , Type type ) {
83
+ if (type instanceof Class <?> clazz ) {
84
+ hints .registerType (clazz , builder -> {
85
+ if (seen .contains (type )) {
86
+ return ;
109
87
}
110
- }
111
- String companionClassName = type .getCanonicalName () + KOTLIN_COMPANION_SUFFIX ;
112
- if (KotlinDetector .isKotlinType (type ) && ClassUtils .isPresent (companionClassName , null )) {
113
- Class <?> companionClass = ClassUtils .resolveClassName (companionClassName , null );
114
- Method serializerMethod = ClassUtils .getMethodIfAvailable (companionClass , "serializer" );
115
- if (serializerMethod != null ) {
116
- hints .registerMethod (serializerMethod );
88
+ seen .add (type );
89
+ if (shouldRegisterMembers (clazz )) {
90
+ builder .withMembers (
91
+ MemberCategory .DECLARED_FIELDS ,
92
+ MemberCategory .INVOKE_DECLARED_CONSTRUCTORS );
93
+ try {
94
+ BeanInfo beanInfo = Introspector .getBeanInfo (clazz );
95
+ PropertyDescriptor [] propertyDescriptors = beanInfo .getPropertyDescriptors ();
96
+ for (PropertyDescriptor propertyDescriptor : propertyDescriptors ) {
97
+ Method writeMethod = propertyDescriptor .getWriteMethod ();
98
+ if (writeMethod != null && writeMethod .getDeclaringClass () != Object .class ) {
99
+ hints .registerMethod (writeMethod , INVOKE );
100
+ MethodParameter methodParameter = MethodParameter .forExecutable (writeMethod , 0 );
101
+ Type methodParameterType = methodParameter .getGenericParameterType ();
102
+ if (!seen .contains (methodParameterType )) {
103
+ registerReflectionHints (hints , seen , methodParameterType );
104
+ }
105
+ }
106
+ Method readMethod = propertyDescriptor .getReadMethod ();
107
+ if (readMethod != null && readMethod .getDeclaringClass () != Object .class ) {
108
+ hints .registerMethod (readMethod , INVOKE );
109
+ MethodParameter methodParameter = MethodParameter .forExecutable (readMethod , -1 );
110
+ Type methodParameterType = methodParameter .getGenericParameterType ();
111
+ if (!seen .contains (methodParameterType )) {
112
+ registerReflectionHints (hints , seen , methodParameterType );
113
+ }
114
+ }
115
+ }
116
+ String companionClassName = clazz .getCanonicalName () + KOTLIN_COMPANION_SUFFIX ;
117
+ if (KotlinDetector .isKotlinType (clazz ) && ClassUtils .isPresent (companionClassName , null )) {
118
+ Class <?> companionClass = ClassUtils .resolveClassName (companionClassName , null );
119
+ Method serializerMethod = ClassUtils .getMethodIfAvailable (companionClass , "serializer" );
120
+ if (serializerMethod != null ) {
121
+ hints .registerMethod (serializerMethod );
122
+ }
123
+ }
124
+ }
125
+ catch (IntrospectionException ex ) {
126
+ if (logger .isDebugEnabled ()) {
127
+ logger .debug ("Ignoring referenced type [" + clazz .getName () + "]: " + ex .getMessage ());
128
+ }
129
+ }
117
130
}
118
- }
119
- }
120
- catch (IntrospectionException ex ) {
121
- if (logger .isDebugEnabled ()) {
122
- logger .debug ("Ignoring referenced type [" + type .getName () + "]: " + ex .getMessage ());
123
- }
131
+ });
124
132
}
133
+ Set <Class <?>> referencedTypes = new LinkedHashSet <>();
134
+ collectReferencedTypes (seen , referencedTypes , type );
135
+ referencedTypes .forEach (referencedType -> registerReflectionHints (hints , seen , referencedType ));
125
136
}
126
137
127
138
private void collectReferencedTypes (Set <Type > seen , Set <Class <?>> types , @ Nullable Type type ) {
@@ -138,4 +149,5 @@ private void collectReferencedTypes(Set<Type> seen, Set<Class<?>> types, @Nullab
138
149
}
139
150
}
140
151
}
152
+
141
153
}
0 commit comments