1
1
/*
2
- * Copyright 2012-2024 the original author or authors.
2
+ * Copyright 2012-2025 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
28
28
import org .junit .jupiter .api .Test ;
29
29
30
30
import org .springframework .aot .hint .ExecutableHint ;
31
+ import org .springframework .aot .hint .FieldHint ;
31
32
import org .springframework .aot .hint .RuntimeHints ;
32
33
import org .springframework .aot .hint .TypeHint ;
33
34
import org .springframework .aot .hint .TypeReference ;
@@ -108,39 +109,39 @@ void registerHintsWhenJavaBean() {
108
109
void registerHintsWhenJavaBeanWithSeveralConstructors () throws NoSuchMethodException {
109
110
RuntimeHints runtimeHints = registerHints (WithSeveralConstructors .class );
110
111
assertThat (runtimeHints .reflection ().typeHints ()).singleElement ()
111
- .satisfies (javaBeanBinding (WithSeveralConstructors .class ,
112
- WithSeveralConstructors .class .getDeclaredConstructor ()));
112
+ .satisfies (javaBeanBinding (WithSeveralConstructors .class )
113
+ . constructor ( WithSeveralConstructors .class .getDeclaredConstructor ()));
113
114
}
114
115
115
116
@ Test
116
117
void registerHintsWhenJavaBeanWithMapOfPojo () {
117
118
RuntimeHints runtimeHints = registerHints (WithMap .class );
118
119
assertThat (runtimeHints .reflection ().typeHints ()).hasSize (2 )
119
- .anySatisfy (javaBeanBinding (WithMap .class , "getAddresses" ))
120
+ .anySatisfy (javaBeanBinding (WithMap .class ). methods ( "getAddresses" ))
120
121
.anySatisfy (javaBeanBinding (Address .class ));
121
122
}
122
123
123
124
@ Test
124
125
void registerHintsWhenJavaBeanWithListOfPojo () {
125
126
RuntimeHints runtimeHints = registerHints (WithList .class );
126
127
assertThat (runtimeHints .reflection ().typeHints ()).hasSize (2 )
127
- .anySatisfy (javaBeanBinding (WithList .class , "getAllAddresses" ))
128
+ .anySatisfy (javaBeanBinding (WithList .class ). methods ( "getAllAddresses" ))
128
129
.anySatisfy (javaBeanBinding (Address .class ));
129
130
}
130
131
131
132
@ Test
132
133
void registerHintsWhenJavaBeanWitArrayOfPojo () {
133
134
RuntimeHints runtimeHints = registerHints (WithArray .class );
134
135
assertThat (runtimeHints .reflection ().typeHints ()).hasSize (2 )
135
- .anySatisfy (javaBeanBinding (WithArray .class , "getAllAddresses" ))
136
+ .anySatisfy (javaBeanBinding (WithArray .class ). methods ( "getAllAddresses" ))
136
137
.anySatisfy (javaBeanBinding (Address .class ));
137
138
}
138
139
139
140
@ Test
140
141
void registerHintsWhenJavaBeanWithListOfJavaType () {
141
142
RuntimeHints runtimeHints = registerHints (WithSimpleList .class );
142
143
assertThat (runtimeHints .reflection ().typeHints ()).singleElement ()
143
- .satisfies (javaBeanBinding (WithSimpleList .class , "getNames" ));
144
+ .satisfies (javaBeanBinding (WithSimpleList .class ). methods ( "getNames" ));
144
145
}
145
146
146
147
@ Test
@@ -177,18 +178,20 @@ void registerHintsWhenHasNestedTypeNotUsedIsIgnored() {
177
178
void registerHintsWhenWhenHasNestedExternalType () {
178
179
RuntimeHints runtimeHints = registerHints (WithExternalNested .class );
179
180
assertThat (runtimeHints .reflection ().typeHints ()).hasSize (3 )
180
- .anySatisfy (
181
- javaBeanBinding (WithExternalNested .class , "getName" , "setName" , "getSampleType" , "setSampleType" ))
182
- .anySatisfy (javaBeanBinding (SampleType .class , "getNested" ))
181
+ .anySatisfy (javaBeanBinding (WithExternalNested .class )
182
+ .methods ("getName" , "setName" , "getSampleType" , "setSampleType" )
183
+ .fields ("name" , "sampleType" ))
184
+ .anySatisfy (javaBeanBinding (SampleType .class ).methods ("getNested" ).fields ("nested" ))
183
185
.anySatisfy (javaBeanBinding (SampleType .Nested .class ));
184
186
}
185
187
186
188
@ Test
187
189
void registerHintsWhenHasRecursiveType () {
188
190
RuntimeHints runtimeHints = registerHints (WithRecursive .class );
189
191
assertThat (runtimeHints .reflection ().typeHints ()).hasSize (2 )
190
- .anySatisfy (javaBeanBinding (WithRecursive .class , "getRecursive" , "setRecursive" ))
191
- .anySatisfy (javaBeanBinding (Recursive .class , "getRecursive" , "setRecursive" ));
192
+ .anySatisfy (
193
+ javaBeanBinding (WithRecursive .class ).methods ("getRecursive" , "setRecursive" ).fields ("recursive" ))
194
+ .anySatisfy (javaBeanBinding (Recursive .class ).methods ("getRecursive" , "setRecursive" ).fields ("recursive" ));
192
195
}
193
196
194
197
@ Test
@@ -203,24 +206,28 @@ void registerHintsWhenValueObjectWithRecursiveType() {
203
206
void registerHintsWhenHasWellKnownTypes () {
204
207
RuntimeHints runtimeHints = registerHints (WithWellKnownTypes .class );
205
208
assertThat (runtimeHints .reflection ().typeHints ()).singleElement ()
206
- .satisfies (javaBeanBinding (WithWellKnownTypes .class , "getApplicationContext" , "setApplicationContext" ,
207
- "getEnvironment" , "setEnvironment" ));
209
+ .satisfies (javaBeanBinding (WithWellKnownTypes .class )
210
+ .methods ("getApplicationContext" , "setApplicationContext" , "getEnvironment" , "setEnvironment" )
211
+ .fields ("applicationContext" , "environment" ));
208
212
}
209
213
210
214
@ Test
211
215
void registerHintsWhenHasCrossReference () {
212
216
RuntimeHints runtimeHints = registerHints (WithCrossReference .class );
213
217
assertThat (runtimeHints .reflection ().typeHints ()).hasSize (3 )
214
- .anySatisfy (javaBeanBinding (WithCrossReference .class , "getCrossReferenceA" , "setCrossReferenceA" ))
215
- .anySatisfy (javaBeanBinding (CrossReferenceA .class , "getCrossReferenceB" , "setCrossReferenceB" ))
216
- .anySatisfy (javaBeanBinding (CrossReferenceB .class , "getCrossReferenceA" , "setCrossReferenceA" ));
218
+ .anySatisfy (javaBeanBinding (WithCrossReference .class ).methods ("getCrossReferenceA" , "setCrossReferenceA" )
219
+ .fields ("crossReferenceA" ))
220
+ .anySatisfy (javaBeanBinding (CrossReferenceA .class ).methods ("getCrossReferenceB" , "setCrossReferenceB" )
221
+ .fields ("crossReferenceB" ))
222
+ .anySatisfy (javaBeanBinding (CrossReferenceB .class ).methods ("getCrossReferenceA" , "setCrossReferenceA" )
223
+ .fields ("crossReferenceA" ));
217
224
}
218
225
219
226
@ Test
220
227
void registerHintsWhenHasUnresolvedGeneric () {
221
228
RuntimeHints runtimeHints = registerHints (WithGeneric .class );
222
229
assertThat (runtimeHints .reflection ().typeHints ()).hasSize (2 )
223
- .anySatisfy (javaBeanBinding (WithGeneric .class , "getGeneric" ))
230
+ .anySatisfy (javaBeanBinding (WithGeneric .class ). methods ( "getGeneric" ). fields ( "generic " ))
224
231
.anySatisfy (javaBeanBinding (GenericObject .class ));
225
232
}
226
233
@@ -246,8 +253,9 @@ void registerHintsWhenHasMultipleNestedClasses() {
246
253
void registerHintsWhenHasPackagePrivateGettersAndSetters () {
247
254
RuntimeHints runtimeHints = registerHints (PackagePrivateGettersAndSetters .class );
248
255
assertThat (runtimeHints .reflection ().typeHints ()).singleElement ()
249
- .satisfies (javaBeanBinding (PackagePrivateGettersAndSetters .class , "getAlpha" , "setAlpha" , "getBravo" ,
250
- "setBravo" ));
256
+ .satisfies (javaBeanBinding (PackagePrivateGettersAndSetters .class )
257
+ .methods ("getAlpha" , "setAlpha" , "getBravo" , "setBravo" )
258
+ .fields ("alpha" , "bravo" ));
251
259
}
252
260
253
261
@ Test
@@ -260,9 +268,9 @@ void registerHintsWhenHasInheritedNestedProperties() {
260
268
.containsExactlyInAnyOrder ("getInheritedNested" , "setInheritedNested" );
261
269
});
262
270
assertThat (runtimeHints .reflection ().getTypeHint (ExtendingProperties .class ))
263
- .satisfies (javaBeanBinding (ExtendingProperties .class , "getBravo" , "setBravo" ));
271
+ .satisfies (javaBeanBinding (ExtendingProperties .class ). methods ( "getBravo" , "setBravo" ). fields ( "bravo " ));
264
272
assertThat (runtimeHints .reflection ().getTypeHint (InheritedNested .class ))
265
- .satisfies (javaBeanBinding (InheritedNested .class , "getAlpha" , "setAlpha" ));
273
+ .satisfies (javaBeanBinding (InheritedNested .class ). methods ( "getAlpha" , "setAlpha" ). fields ( "alpha " ));
266
274
}
267
275
268
276
@ Test
@@ -275,11 +283,11 @@ void registerHintsWhenHasComplexNestedProperties() {
275
283
.containsExactlyInAnyOrder ("getCount" , "setCount" );
276
284
});
277
285
assertThat (runtimeHints .reflection ().getTypeHint (ListenerRetry .class ))
278
- .satisfies (javaBeanBinding (ListenerRetry .class , "isStateless" , "setStateless" ));
286
+ .satisfies (javaBeanBinding (ListenerRetry .class ). methods ( "isStateless" , "setStateless" ). fields ( "stateless " ));
279
287
assertThat (runtimeHints .reflection ().getTypeHint (Simple .class ))
280
- .satisfies (javaBeanBinding (Simple .class , "getRetry" ));
288
+ .satisfies (javaBeanBinding (Simple .class ). methods ( "getRetry" ). fields ( "retry " ));
281
289
assertThat (runtimeHints .reflection ().getTypeHint (ComplexNestedProperties .class ))
282
- .satisfies (javaBeanBinding (ComplexNestedProperties .class , "getSimple" ));
290
+ .satisfies (javaBeanBinding (ComplexNestedProperties .class ). methods ( "getSimple" ). fields ( "simple " ));
283
291
}
284
292
285
293
@ Test
@@ -292,17 +300,8 @@ void registerHintsDoesNotThrowWhenParameterInformationForConstructorBindingIsNot
292
300
assertThatNoException ().isThrownBy (() -> registerHints (PoolProperties .class ));
293
301
}
294
302
295
- private Consumer <TypeHint > javaBeanBinding (Class <?> type , String ... expectedMethods ) {
296
- return javaBeanBinding (type , type .getDeclaredConstructors ()[0 ], expectedMethods );
297
- }
298
-
299
- private Consumer <TypeHint > javaBeanBinding (Class <?> type , Constructor <?> constructor , String ... expectedMethods ) {
300
- return (entry ) -> {
301
- assertThat (entry .getType ()).isEqualTo (TypeReference .of (type ));
302
- assertThat (entry .constructors ()).singleElement ().satisfies (match (constructor ));
303
- assertThat (entry .getMemberCategories ()).isEmpty ();
304
- assertThat (entry .methods ()).extracting (ExecutableHint ::getName ).containsExactlyInAnyOrder (expectedMethods );
305
- };
303
+ private JavaBeanBinding javaBeanBinding (Class <?> type ) {
304
+ return new JavaBeanBinding (type );
306
305
}
307
306
308
307
private Consumer <TypeHint > valueObjectBinding (Class <?> type ) {
@@ -318,7 +317,7 @@ private Consumer<TypeHint> valueObjectBinding(Class<?> type, Constructor<?> cons
318
317
};
319
318
}
320
319
321
- private Consumer <ExecutableHint > match (Constructor <?> constructor ) {
320
+ private static Consumer <ExecutableHint > match (Constructor <?> constructor ) {
322
321
return (executableHint ) -> {
323
322
assertThat (executableHint .getName ()).isEqualTo ("<init>" );
324
323
assertThat (Arrays .stream (constructor .getParameterTypes ()).map (TypeReference ::of ).toList ())
@@ -804,4 +803,49 @@ public void setStateless(boolean stateless) {
804
803
805
804
}
806
805
806
+ private static final class JavaBeanBinding implements Consumer <TypeHint > {
807
+
808
+ private final Class <?> type ;
809
+
810
+ private Constructor <?> constructor ;
811
+
812
+ private List <String > expectedMethods = Collections .emptyList ();
813
+
814
+ private List <String > expectedFields = Collections .emptyList ();
815
+
816
+ private JavaBeanBinding (Class <?> type ) {
817
+ this .type = type ;
818
+ this .constructor = this .type .getDeclaredConstructors ()[0 ];
819
+ }
820
+
821
+ @ Override
822
+ public void accept (TypeHint entry ) {
823
+ assertThat (entry .getType ()).isEqualTo (TypeReference .of (this .type ));
824
+ assertThat (entry .constructors ()).singleElement ().satisfies (match (this .constructor ));
825
+ assertThat (entry .getMemberCategories ()).isEmpty ();
826
+ assertThat (entry .methods ()).as ("Methods requiring reflection" )
827
+ .extracting (ExecutableHint ::getName )
828
+ .containsExactlyInAnyOrderElementsOf (this .expectedMethods );
829
+ assertThat (entry .fields ()).as ("Fields requiring reflection" )
830
+ .extracting (FieldHint ::getName )
831
+ .containsExactlyInAnyOrderElementsOf (this .expectedFields );
832
+ }
833
+
834
+ private JavaBeanBinding constructor (Constructor <?> constructor ) {
835
+ this .constructor = constructor ;
836
+ return this ;
837
+ }
838
+
839
+ private JavaBeanBinding methods (String ... methods ) {
840
+ this .expectedMethods = List .of (methods );
841
+ return this ;
842
+ }
843
+
844
+ private JavaBeanBinding fields (String ... fields ) {
845
+ this .expectedFields = List .of (fields );
846
+ return this ;
847
+ }
848
+
849
+ }
850
+
807
851
}
0 commit comments