diff --git a/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java b/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java index b6f09e3d118..d5a063e3b8d 100644 --- a/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java +++ b/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java @@ -151,15 +151,15 @@ class InstrumentedMethodTests { @Test void classGetConstructorShouldMatchInstrospectConstructorHint() { - hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(Collections.emptyList(), - constructorHint -> constructorHint.withMode(ExecutableMode.INTROSPECT))); + hints.reflection().registerType(String.class,typeHint -> + typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor); } @Test void classGetConstructorShouldMatchInvokeConstructorHint() { - hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(Collections.emptyList(), - constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE))); + hints.reflection().registerType(String.class, typeHint -> + typeHint.withConstructor(Collections.emptyList(),ExecutableMode.INVOKE)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor); } @@ -201,15 +201,15 @@ class InstrumentedMethodTests { @Test void classGetDeclaredConstructorShouldMatchInstrospectConstructorHint() { - hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), - constructorHint -> constructorHint.withMode(ExecutableMode.INTROSPECT))); + hints.reflection().registerType(String.class, typeHint -> + typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), ExecutableMode.INTROSPECT)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor); } @Test void classGetDeclaredConstructorShouldMatchInvokeConstructorHint() { - hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), - constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE))); + hints.reflection().registerType(String.class, typeHint -> + typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), ExecutableMode.INVOKE)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor); } @@ -237,7 +237,7 @@ class InstrumentedMethodTests { RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE) .onInstance(String.class.getConstructor()).returnValue("").build(); hints.reflection().registerType(String.class, typeHint -> - typeHint.withConstructor(Collections.emptyList(), constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE))); + typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INVOKE)); assertThatInvocationMatches(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation); } @@ -246,7 +246,7 @@ class InstrumentedMethodTests { RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE) .onInstance(String.class.getConstructor()).returnValue("").build(); hints.reflection().registerType(String.class, typeHint -> - typeHint.withConstructor(Collections.emptyList(), constructorHint -> constructorHint.withMode(ExecutableMode.INTROSPECT))); + typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT)); assertThatInvocationDoesNotMatch(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation); } @@ -285,7 +285,7 @@ class InstrumentedMethodTests { void classGetDeclaredMethodShouldMatchIntrospectMethodHint() { List parameterTypes = TypeReference.listOf(int.class, float.class); hints.reflection().registerType(String.class, typeHint -> - typeHint.withMethod("scale", parameterTypes, methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT))); + typeHint.withMethod("scale", parameterTypes, ExecutableMode.INTROSPECT)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod); } @@ -293,7 +293,7 @@ class InstrumentedMethodTests { void classGetDeclaredMethodShouldMatchInvokeMethodHint() { List parameterTypes = TypeReference.listOf(int.class, float.class); hints.reflection().registerType(String.class, typeHint -> - typeHint.withMethod("scale", parameterTypes, methodHint -> methodHint.withMode(ExecutableMode.INVOKE))); + typeHint.withMethod("scale", parameterTypes, ExecutableMode.INVOKE)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod); } @@ -378,14 +378,14 @@ class InstrumentedMethodTests { @Test void classGetMethodShouldMatchIntrospectMethodHint() { hints.reflection().registerType(String.class, typeHint -> - typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT))); + typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod); } @Test void classGetMethodShouldMatchInvokeMethodHint() { hints.reflection().registerType(String.class, typeHint -> - typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INVOKE))); + typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INVOKE)); assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod); } @@ -412,7 +412,7 @@ class InstrumentedMethodTests { RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.METHOD_INVOKE) .onInstance(String.class.getMethod("startsWith", String.class)).withArguments("testString", new Object[] { "test" }).build(); hints.reflection().registerType(String.class, typeHint -> typeHint.withMethod("startsWith", - TypeReference.listOf(String.class), methodHint -> methodHint.withMode(ExecutableMode.INVOKE))); + TypeReference.listOf(String.class), ExecutableMode.INVOKE)); assertThatInvocationMatches(InstrumentedMethod.METHOD_INVOKE, invocation); } @@ -421,7 +421,7 @@ class InstrumentedMethodTests { RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.METHOD_INVOKE) .onInstance(String.class.getMethod("toString")).withArguments("", new Object[0]).build(); hints.reflection().registerType(String.class, typeHint -> - typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT))); + typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT)); assertThatInvocationDoesNotMatch(InstrumentedMethod.METHOD_INVOKE, invocation); } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java index 519eba94a68..e7781caabdf 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java @@ -173,6 +173,16 @@ public final class TypeHint implements ConditionalHint { return this; } + /** + * Register the need for reflection on the field with the specified name, + * enabling write access. + * @param name the name of the field + * @return {@code this}, to facilitate method chaining + */ + public Builder withField(String name) { + return withField(name, fieldHint -> {}); + } + /** * Register the need for reflection on the constructor with the specified * parameter types. @@ -189,6 +199,27 @@ public final class TypeHint implements ConditionalHint { return this; } + /** + * Register the need for reflection on the constructor with the specified + * parameter types, using the specified {@link ExecutableMode}. + * @param parameterTypes the parameter types of the constructor + * @param mode the requested mode + * @return {@code this}, to facilitate method chaining + */ + public Builder withConstructor(List parameterTypes, ExecutableMode mode) { + return withConstructor(parameterTypes, constructorHint -> constructorHint.withMode(mode)); + } + + /** + * Register the need for reflection on the constructor with the specified + * parameter types, enabling {@link ExecutableMode#INVOKE}. + * @param parameterTypes the parameter types of the constructor + * @return {@code this}, to facilitate method chaining + */ + public Builder withConstructor(List parameterTypes) { + return withConstructor(parameterTypes, ExecutableMode.INVOKE); + } + /** * Register the need for reflection on the method with the specified name * and parameter types. @@ -205,6 +236,29 @@ public final class TypeHint implements ConditionalHint { return this; } + /** + * Register the need for reflection on the method with the specified name + * and parameter types, using the specified {@link ExecutableMode}. + * @param name the name of the method + * @param parameterTypes the parameter types of the constructor + * @param mode the requested mode + * @return {@code this}, to facilitate method chaining + */ + public Builder withMethod(String name, List parameterTypes, ExecutableMode mode) { + return withMethod(name, parameterTypes, methodHint -> methodHint.withMode(mode)); + } + + /** + * Register the need for reflection on the method with the specified name + * and parameter types, enabling {@link ExecutableMode#INVOKE}. + * @param name the name of the method + * @param parameterTypes the parameter types of the constructor + * @return {@code this}, to facilitate method chaining + */ + public Builder withMethod(String name, List parameterTypes) { + return withMethod(name, parameterTypes, ExecutableMode.INVOKE); + } + /** * Adds the specified {@linkplain MemberCategory member categories}. * @param memberCategories the categories to apply diff --git a/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java b/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java index f66b83120c4..2bdf754c883 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/TypeHintTests.java @@ -17,6 +17,7 @@ package org.springframework.aot.hint; import java.util.List; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; @@ -54,16 +55,38 @@ class TypeHintTests { } @Test - void createWithField() { - TypeHint hint = TypeHint.of(TypeReference.of(String.class)) - .withField("value", fieldHint -> fieldHint.allowWrite(true)).build(); - assertThat(hint.fields()).singleElement().satisfies(fieldHint -> { + void createWithFieldAllowsWriteByDefault() { + assertFieldHint(TypeHint.of(TypeReference.of(String.class)) + .withField("value"), fieldHint -> { assertThat(fieldHint.getName()).isEqualTo("value"); assertThat(fieldHint.isAllowWrite()).isTrue(); assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); }); } + @Test + void createWithFieldAndEmptyCustomizerAppliesConsistentDefault() { + assertFieldHint(TypeHint.of(TypeReference.of(String.class)) + .withField("value", fieldHint -> {}), fieldHint -> { + assertThat(fieldHint.getName()).isEqualTo("value"); + assertThat(fieldHint.isAllowWrite()).isTrue(); + assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); + }); + } + + @Test + void createWithFieldAndCustomizerAppliesCustomization() { + assertFieldHint(TypeHint.of(TypeReference.of(String.class)) + .withField("value", fieldHint -> { + fieldHint.allowWrite(false); + fieldHint.allowUnsafeAccess(true); + }), fieldHint -> { + assertThat(fieldHint.getName()).isEqualTo("value"); + assertThat(fieldHint.isAllowWrite()).isFalse(); + assertThat(fieldHint.isAllowUnsafeAccess()).isTrue(); + }); + } + @Test void createWithFieldReuseBuilder() { Builder builder = TypeHint.of(TypeReference.of(String.class)); @@ -72,33 +95,69 @@ class TypeHintTests { fieldHint.allowWrite(true); fieldHint.allowUnsafeAccess(false); }); - TypeHint hint = builder.build(); - assertThat(hint.fields()).singleElement().satisfies(fieldHint -> { + assertFieldHint(builder, fieldHint -> { assertThat(fieldHint.getName()).isEqualTo("value"); assertThat(fieldHint.isAllowWrite()).isTrue(); assertThat(fieldHint.isAllowUnsafeAccess()).isFalse(); }); } + void assertFieldHint(Builder builder, Consumer fieldHint) { + TypeHint hint = builder.build(); + assertThat(hint.fields()).singleElement().satisfies(fieldHint); + assertThat(hint.constructors()).isEmpty(); + assertThat(hint.methods()).isEmpty(); + assertThat(hint.getMemberCategories()).isEmpty(); + } + @Test void createWithConstructor() { List parameterTypes = TypeReference.listOf(byte[].class, int.class); - TypeHint hint = TypeHint.of(TypeReference.of(String.class)).withConstructor(parameterTypes, - constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE)).build(); - assertThat(hint.constructors()).singleElement().satisfies(constructorHint -> { + assertConstructorHint(TypeHint.of(TypeReference.of(String.class)) + .withConstructor(parameterTypes), constructorHint -> { assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes); assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE); }); } + @Test + void createWithConstructorAndMode() { + List parameterTypes = TypeReference.listOf(byte[].class, int.class); + assertConstructorHint(TypeHint.of(TypeReference.of(String.class)) + .withConstructor(parameterTypes, ExecutableMode.INTROSPECT), constructorHint -> { + assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes); + assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT); + }); + } + + @Test + void createWithConstructorAndEmptyCustomizerAppliesConsistentDefault() { + List parameterTypes = TypeReference.listOf(byte[].class, int.class); + assertConstructorHint(TypeHint.of(TypeReference.of(String.class)) + .withConstructor(parameterTypes, constructorHint -> {}), constructorHint -> { + assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes); + assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE); + }); + } + + @Test + void createWithConstructorAndCustomizerAppliesCustomization() { + List parameterTypes = TypeReference.listOf(byte[].class, int.class); + assertConstructorHint(TypeHint.of(TypeReference.of(String.class)) + .withConstructor(parameterTypes, constructorHint -> + constructorHint.withMode(ExecutableMode.INTROSPECT)), constructorHint -> { + assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes); + assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT); + }); + } + @Test void createConstructorReuseBuilder() { List parameterTypes = TypeReference.listOf(byte[].class, int.class); - Builder builder = TypeHint.of(TypeReference.of(String.class)).withConstructor(parameterTypes, - constructorHint -> constructorHint.withMode(ExecutableMode.INTROSPECT)); - TypeHint hint = builder.withConstructor(parameterTypes, constructorHint -> - constructorHint.withMode(ExecutableMode.INVOKE)).build(); - assertThat(hint.constructors()).singleElement().satisfies(constructorHint -> { + Builder builder = TypeHint.of(TypeReference.of(String.class)) + .withConstructor(parameterTypes, ExecutableMode.INTROSPECT); + assertConstructorHint(builder.withConstructor(parameterTypes, constructorHint -> + constructorHint.withMode(ExecutableMode.INVOKE)), constructorHint -> { assertThat(constructorHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE); }); @@ -109,34 +168,74 @@ class TypeHintTests { List parameterTypes = TypeReference.listOf(byte[].class, int.class); Builder builder = TypeHint.of(TypeReference.of(String.class)).withConstructor(parameterTypes, constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE)); - TypeHint hint = builder.withConstructor(parameterTypes, constructorHint -> - constructorHint.withMode(ExecutableMode.INTROSPECT)).build(); - assertThat(hint.constructors()).singleElement().satisfies(constructorHint -> { + assertConstructorHint(builder.withConstructor(parameterTypes, constructorHint -> + constructorHint.withMode(ExecutableMode.INTROSPECT)), constructorHint -> { assertThat(constructorHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE); }); } + void assertConstructorHint(Builder builder, Consumer constructorHint) { + TypeHint hint = builder.build(); + assertThat(hint.fields()).isEmpty(); + assertThat(hint.constructors()).singleElement().satisfies(constructorHint); + assertThat(hint.methods()).isEmpty(); + assertThat(hint.getMemberCategories()).isEmpty(); + } + @Test void createWithMethod() { List parameterTypes = List.of(TypeReference.of(char[].class)); - TypeHint hint = TypeHint.of(TypeReference.of(String.class)).withMethod("valueOf", parameterTypes, - methodHint -> methodHint.withMode(ExecutableMode.INVOKE)).build(); - assertThat(hint.methods()).singleElement().satisfies(methodHint -> { + assertMethodHint(TypeHint.of(TypeReference.of(String.class)) + .withMethod("valueOf", parameterTypes), methodHint -> { assertThat(methodHint.getName()).isEqualTo("valueOf"); assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE); }); } + @Test + void createWithMethodAndMode() { + List parameterTypes = List.of(TypeReference.of(char[].class)); + assertMethodHint(TypeHint.of(TypeReference.of(String.class)) + .withMethod("valueOf", parameterTypes, ExecutableMode.INTROSPECT), methodHint -> { + assertThat(methodHint.getName()).isEqualTo("valueOf"); + assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); + assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT); + }); + } + + @Test + void createWithMethodAndEmptyCustomizerAppliesConsistentDefault() { + List parameterTypes = List.of(TypeReference.of(char[].class)); + assertMethodHint(TypeHint.of(TypeReference.of(String.class)) + .withMethod("valueOf", parameterTypes, methodHint -> {}), methodHint -> { + assertThat(methodHint.getName()).isEqualTo("valueOf"); + assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); + assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE); + }); + } + + @Test + void createWithMethodAndCustomizerAppliesCustomization() { + List parameterTypes = List.of(TypeReference.of(char[].class)); + assertMethodHint(TypeHint.of(TypeReference.of(String.class)) + .withMethod("valueOf", parameterTypes, methodHint -> + methodHint.withMode(ExecutableMode.INTROSPECT)), methodHint -> { + assertThat(methodHint.getName()).isEqualTo("valueOf"); + assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); + assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT); + }); + } + + @Test void createWithMethodReuseBuilder() { List parameterTypes = TypeReference.listOf(char[].class); - Builder builder = TypeHint.of(TypeReference.of(String.class)).withMethod("valueOf", parameterTypes, - methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)); - TypeHint hint = builder.withMethod("valueOf", parameterTypes, - methodHint -> methodHint.withMode(ExecutableMode.INVOKE)).build(); - assertThat(hint.methods()).singleElement().satisfies(methodHint -> { + Builder builder = TypeHint.of(TypeReference.of(String.class)) + .withMethod("valueOf", parameterTypes, ExecutableMode.INTROSPECT); + assertMethodHint(builder.withMethod("valueOf", parameterTypes, + methodHint -> methodHint.withMode(ExecutableMode.INVOKE)), methodHint -> { assertThat(methodHint.getName()).isEqualTo("valueOf"); assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE); @@ -146,17 +245,25 @@ class TypeHintTests { @Test void createWithMethodReuseBuilderAndApplyExecutableModePrecedence() { List parameterTypes = TypeReference.listOf(char[].class); - Builder builder = TypeHint.of(TypeReference.of(String.class)).withMethod("valueOf", parameterTypes, - methodHint -> methodHint.withMode(ExecutableMode.INVOKE)); - TypeHint hint = builder.withMethod("valueOf", parameterTypes, - methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)).build(); - assertThat(hint.methods()).singleElement().satisfies(methodHint -> { + Builder builder = TypeHint.of(TypeReference.of(String.class)) + .withMethod("valueOf", parameterTypes, ExecutableMode.INVOKE); + assertMethodHint(builder.withMethod("valueOf", parameterTypes, + methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)), methodHint -> { assertThat(methodHint.getName()).isEqualTo("valueOf"); assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes); assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE); }); } + void assertMethodHint(Builder builder, Consumer methodHint) { + TypeHint hint = builder.build(); + assertThat(hint.fields()).isEmpty(); + assertThat(hint.constructors()).isEmpty(); + assertThat(hint.methods()).singleElement().satisfies(methodHint); + assertThat(hint.getMemberCategories()).isEmpty(); + } + + @Test void createWithMemberCategory() { TypeHint hint = TypeHint.of(TypeReference.of(String.class)) diff --git a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java index 3706197d509..6df28fe5711 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java @@ -157,7 +157,7 @@ class ReflectionHintsPredicatesTests { @Test void constructorIntrospectionMatchesConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(Collections.emptyList(), constructorHint -> {})); + typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT)); assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); } @@ -192,16 +192,14 @@ class ReflectionHintsPredicatesTests { @Test void constructorInvocationDoesNotMatchConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint. - withConstructor(Collections.emptyList(), constructorHint -> - constructorHint.withMode(ExecutableMode.INTROSPECT))); + withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT)); assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).invoke()); } @Test void constructorInvocationMatchesConstructorInvocationHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint. - withConstructor(Collections.emptyList(), constructorHint -> - constructorHint.withMode(ExecutableMode.INVOKE))); + withConstructor(Collections.emptyList(), ExecutableMode.INVOKE)); assertPredicateMatches(reflection.onConstructor(publicConstructor).invoke()); } @@ -236,7 +234,7 @@ class ReflectionHintsPredicatesTests { @Test void privateConstructorIntrospectionMatchesConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(TypeReference.listOf(String.class), constructorHint -> {})); + typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect()); } @@ -271,16 +269,14 @@ class ReflectionHintsPredicatesTests { @Test void privateConstructorInvocationDoesNotMatchConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(TypeReference.listOf(String.class), constructorHint -> - constructorHint.withMode(ExecutableMode.INTROSPECT))); + typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).invoke()); } @Test void privateConstructorInvocationMatchesConstructorInvocationHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(TypeReference.listOf(String.class), - constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE))); + typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INVOKE)); assertPredicateMatches(reflection.onConstructor(privateConstructor).invoke()); } @@ -319,8 +315,8 @@ class ReflectionHintsPredicatesTests { @Test void methodIntrospectionMatchesMethodHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("publicMethod", Collections.emptyList(), methodHint -> { - })); + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withMethod("publicMethod", Collections.emptyList(), ExecutableMode.INTROSPECT)); assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); } @@ -350,15 +346,15 @@ class ReflectionHintsPredicatesTests { @Test void methodInvocationDoesNotMatchMethodHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("publicMethod", Collections.emptyList(), - methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT))); + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withMethod("publicMethod", Collections.emptyList(), ExecutableMode.INTROSPECT)); assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").invoke()); } @Test void methodInvocationMatchesMethodInvocationHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("publicMethod", Collections.emptyList(), - methodHint -> methodHint.withMode(ExecutableMode.INVOKE))); + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withMethod("publicMethod", Collections.emptyList(), ExecutableMode.INVOKE)); assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").invoke()); } @@ -388,8 +384,8 @@ class ReflectionHintsPredicatesTests { @Test void privateMethodIntrospectionMatchesMethodHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("privateMethod", Collections.emptyList(), methodHint -> { - })); + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT)); assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").introspect()); } @@ -419,14 +415,15 @@ class ReflectionHintsPredicatesTests { @Test void privateMethodInvocationDoesNotMatchMethodHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("privateMethod", Collections.emptyList(), - methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT))); + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT)); assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "privateMethod").invoke()); } @Test void privateMethodInvocationMatchesMethodInvocationHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("privateMethod", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INVOKE))); + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INVOKE)); assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").invoke()); } diff --git a/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java b/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java index 121e75c9ebf..833ad61d6f9 100644 --- a/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java +++ b/spring-core/src/test/java/org/springframework/aot/nativex/FileNativeConfigurationWriterTests.java @@ -111,11 +111,9 @@ public class FileNativeConfigurationWriterTests { fieldBuilder.allowWrite(true); fieldBuilder.allowUnsafeAccess(true); }) - .withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), constructorHint -> - constructorHint.withMode(ExecutableMode.INTROSPECT)) - .withMethod("setDefaultCharset", TypeReference.listOf(Charset.class), ctorBuilder -> {}) - .withMethod("getDefaultCharset", Collections.emptyList(), constructorHint -> - constructorHint.withMode(ExecutableMode.INTROSPECT)); + .withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT) + .withMethod("setDefaultCharset", TypeReference.listOf(Charset.class)) + .withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT); }); generator.write(hints); assertEquals(""" diff --git a/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java b/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java index e3c547a79b2..62abe02908c 100644 --- a/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java +++ b/spring-core/src/test/java/org/springframework/aot/nativex/ReflectionHintsWriterTests.java @@ -49,26 +49,22 @@ public class ReflectionHintsWriterTests { @Test void one() throws JSONException { ReflectionHints hints = new ReflectionHints(); - hints.registerType(StringDecoder.class, builder -> { - builder - .onReachableType(TypeReference.of(String.class)) - .withMembers(MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, - MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, - MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, - MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS, - MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES) - .withField("DEFAULT_CHARSET", fieldBuilder -> fieldBuilder.allowWrite(false)) - .withField("defaultCharset", fieldBuilder -> { - fieldBuilder.allowWrite(true); - fieldBuilder.allowUnsafeAccess(true); - }) - .withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), constructorHint -> - constructorHint.withMode(ExecutableMode.INTROSPECT)) - .withMethod("setDefaultCharset", List.of(TypeReference.of(Charset.class)), ctorBuilder -> {}) - .withMethod("getDefaultCharset", Collections.emptyList(), constructorHint -> - constructorHint.withMode(ExecutableMode.INTROSPECT)); - }); + hints.registerType(StringDecoder.class, builder -> builder + .onReachableType(TypeReference.of(String.class)) + .withMembers(MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS, + MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, + MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, + MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS, + MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS, + MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES) + .withField("DEFAULT_CHARSET", fieldBuilder -> fieldBuilder.allowWrite(false)) + .withField("defaultCharset", fieldBuilder -> { + fieldBuilder.allowWrite(true); + fieldBuilder.allowUnsafeAccess(true); + }) + .withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT) + .withMethod("setDefaultCharset", List.of(TypeReference.of(Charset.class))) + .withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT)); assertEquals(""" [ { @@ -120,7 +116,7 @@ public class ReflectionHintsWriterTests { void queriedMethods() throws JSONException { ReflectionHints hints = new ReflectionHints(); hints.registerType(Integer.class, builder -> builder.withMethod("parseInt", - TypeReference.listOf(String.class), b -> b.withMode(ExecutableMode.INTROSPECT))); + TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); assertEquals(""" [ @@ -141,7 +137,7 @@ public class ReflectionHintsWriterTests { void methods() throws JSONException { ReflectionHints hints = new ReflectionHints(); hints.registerType(Integer.class, builder -> builder.withMethod("parseInt", - TypeReference.listOf(String.class), b -> b.withMode(ExecutableMode.INVOKE))); + TypeReference.listOf(String.class), ExecutableMode.INVOKE)); assertEquals(""" [ @@ -162,7 +158,7 @@ public class ReflectionHintsWriterTests { void methodWithInnerClassParameter() throws JSONException { ReflectionHints hints = new ReflectionHints(); hints.registerType(Integer.class, builder -> builder.withMethod("test", - TypeReference.listOf(Inner.class), b -> b.withMode(ExecutableMode.INVOKE))); + TypeReference.listOf(Inner.class), ExecutableMode.INVOKE)); assertEquals(""" [ @@ -183,9 +179,9 @@ public class ReflectionHintsWriterTests { void methodAndQueriedMethods() throws JSONException { ReflectionHints hints = new ReflectionHints(); hints.registerType(Integer.class, builder -> builder.withMethod("parseInt", - TypeReference.listOf(String.class), b -> b.withMode(ExecutableMode.INVOKE))); + TypeReference.listOf(String.class), ExecutableMode.INVOKE)); hints.registerType(Integer.class, builder -> builder.withMethod("parseInt", - TypeReference.listOf(String.class, int.class), b -> b.withMode(ExecutableMode.INTROSPECT))); + TypeReference.listOf(String.class, int.class), ExecutableMode.INTROSPECT)); assertEquals(""" [