diff --git a/spring-core/src/main/java/org/springframework/aot/hint/ExecutableMode.java b/spring-core/src/main/java/org/springframework/aot/hint/ExecutableMode.java index 7082859e75..2de9e84c44 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/ExecutableMode.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/ExecutableMode.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,10 @@ public enum ExecutableMode { /** * Only retrieving the {@link Executable} and its metadata is required. + * @deprecated with no replacement since introspection is included + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. */ + @Deprecated(since= "7.0", forRemoval = true) INTROSPECT, /** diff --git a/spring-core/src/main/java/org/springframework/aot/hint/MemberCategory.java b/spring-core/src/main/java/org/springframework/aot/hint/MemberCategory.java index 2d09bb0e45..05b60208a6 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/MemberCategory.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/MemberCategory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,32 +32,62 @@ import java.lang.reflect.Method; public enum MemberCategory { /** - * A category that represents public {@linkplain Field fields}. + * A category that represents introspection on public {@linkplain Field fields}. + * @deprecated with no replacement since introspection is included + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. + * Use {@link #INVOKE_PUBLIC_FIELDS} if getting/setting field values is required. * @see Class#getFields() */ + @Deprecated(since = "7.0", forRemoval = true) PUBLIC_FIELDS, /** - * A category that represents {@linkplain Class#getDeclaredFields() declared + * A category that represents introspection on {@linkplain Class#getDeclaredFields() declared * fields}: all fields defined by the class but not inherited fields. + * @deprecated with no replacement since introspection is included + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. + * Use {@link #INVOKE_DECLARED_FIELDS} if getting/setting field values is required. * @see Class#getDeclaredFields() */ + @Deprecated(since = "7.0", forRemoval = true) DECLARED_FIELDS, + /** + * A category that represents getting/setting values on public {@linkplain Field fields}. + * @see Field#get(Object) + * @see Field#set(Object, Object) + * @since 7.0 + */ + INVOKE_PUBLIC_FIELDS, + + /** + * A category that represents getting/setting values on declared {@linkplain Field fields}. + * @see Field#get(Object) + * @see Field#set(Object, Object) + * @since 7.0 + */ + INVOKE_DECLARED_FIELDS, + /** * A category that defines public {@linkplain Constructor constructors} can * be introspected but not invoked. + * @deprecated with no replacement since introspection is included + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. * @see Class#getConstructors() * @see ExecutableMode#INTROSPECT */ + @Deprecated(since = "7.0", forRemoval = true) INTROSPECT_PUBLIC_CONSTRUCTORS, /** * A category that defines {@linkplain Class#getDeclaredConstructors() all * constructors} can be introspected but not invoked. + * @deprecated with no replacement since introspection is included + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. * @see Class#getDeclaredConstructors() * @see ExecutableMode#INTROSPECT */ + @Deprecated(since = "7.0", forRemoval = true) INTROSPECT_DECLARED_CONSTRUCTORS, /** @@ -79,17 +109,23 @@ public enum MemberCategory { /** * A category that defines public {@linkplain Method methods}, including * inherited ones, can be introspected but not invoked. + * @deprecated with no replacement since introspection is added by default + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. * @see Class#getMethods() * @see ExecutableMode#INTROSPECT */ + @Deprecated(since = "7.0", forRemoval = true) INTROSPECT_PUBLIC_METHODS, /** * A category that defines {@linkplain Class#getDeclaredMethods() all * methods}, excluding inherited ones, can be introspected but not invoked. + * @deprecated with no replacement since introspection is added by default + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. * @see Class#getDeclaredMethods() * @see ExecutableMode#INTROSPECT */ + @Deprecated(since = "7.0", forRemoval = true) INTROSPECT_DECLARED_METHODS, /** @@ -114,7 +150,10 @@ public enum MemberCategory { *

Contrary to other categories, this does not register any particular * reflection for inner classes but rather makes sure they are available * via a call to {@link Class#getClasses}. + * @deprecated with no replacement since introspection is included + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. */ + @Deprecated(since = "7.0", forRemoval = true) PUBLIC_CLASSES, /** @@ -123,7 +162,10 @@ public enum MemberCategory { *

Contrary to other categories, this does not register any particular * reflection for inner classes but rather makes sure they are available * via a call to {@link Class#getDeclaredClasses}. + * @deprecated with no replacement since introspection is included + * when {@link ReflectionHints#registerType(Class, MemberCategory...) adding a reflection hint for a type}. */ + @Deprecated(since = "7.0", forRemoval = true) DECLARED_CLASSES } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java index a9f87de77a..69ba572e35 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java @@ -255,6 +255,7 @@ public class ReflectionHintsPredicates { } + @SuppressWarnings("removal") public abstract static class ExecutableHintPredicate implements Predicate { protected final T executable; @@ -299,6 +300,7 @@ public class ReflectionHintsPredicates { } + @SuppressWarnings("removal") public static class ConstructorHintPredicate extends ExecutableHintPredicate> { ConstructorHintPredicate(Constructor constructor) { @@ -308,28 +310,17 @@ public class ReflectionHintsPredicates { @Override public boolean test(RuntimeHints runtimeHints) { return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) - .withAnyMemberCategory(getPublicMemberCategories()) - .and(hints -> Modifier.isPublic(this.executable.getModifiers()))) - .or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())).withAnyMemberCategory(getDeclaredMemberCategories())) + .and(hints -> this.executableMode == ExecutableMode.INTROSPECT)) + .or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) + .withMemberCategory(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS) + .and(hints -> Modifier.isPublic(this.executable.getModifiers())) + .and(hints -> this.executableMode == ExecutableMode.INVOKE)) + .or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) + .withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS) + .and(hints -> this.executableMode == ExecutableMode.INVOKE)) .or(exactMatch()).test(runtimeHints); } - MemberCategory[] getPublicMemberCategories() { - if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, - MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS }; - } - return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS }; - } - - MemberCategory[] getDeclaredMemberCategories() { - if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] { MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, - MemberCategory.INVOKE_DECLARED_CONSTRUCTORS }; - } - return new MemberCategory[] { MemberCategory.INVOKE_DECLARED_CONSTRUCTORS }; - } - @Override Predicate exactMatch() { return hints -> { @@ -343,6 +334,7 @@ public class ReflectionHintsPredicates { } + @SuppressWarnings("removal") public static class MethodHintPredicate extends ExecutableHintPredicate { MethodHintPredicate(Method method) { @@ -352,31 +344,18 @@ public class ReflectionHintsPredicates { @Override public boolean test(RuntimeHints runtimeHints) { return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) - .withAnyMemberCategory(getPublicMemberCategories()) - .and(hints -> Modifier.isPublic(this.executable.getModifiers()))) - .or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) - .withAnyMemberCategory(getDeclaredMemberCategories()) - .and(hints -> !Modifier.isPublic(this.executable.getModifiers()))) + .and(hints -> this.executableMode == ExecutableMode.INTROSPECT)) + .or((new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) + .withMemberCategory(MemberCategory.INVOKE_PUBLIC_METHODS) + .and(hints -> Modifier.isPublic(this.executable.getModifiers())) + .and(hints -> this.executableMode == ExecutableMode.INVOKE))) + .or((new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) + .withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS) + .and(hints -> !Modifier.isPublic(this.executable.getModifiers())) + .and(hints -> this.executableMode == ExecutableMode.INVOKE))) .or(exactMatch()).test(runtimeHints); } - MemberCategory[] getPublicMemberCategories() { - if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_METHODS, - MemberCategory.INVOKE_PUBLIC_METHODS }; - } - return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_METHODS }; - } - - MemberCategory[] getDeclaredMemberCategories() { - - if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] { MemberCategory.INTROSPECT_DECLARED_METHODS, - MemberCategory.INVOKE_DECLARED_METHODS }; - } - return new MemberCategory[] { MemberCategory.INVOKE_DECLARED_METHODS }; - } - @Override Predicate exactMatch() { return hints -> { @@ -394,31 +373,40 @@ public class ReflectionHintsPredicates { private final Field field; + @Nullable + private ExecutableMode executableMode; + FieldHintPredicate(Field field) { this.field = field; } + /** + * Refine the current predicate to only match if an invocation hint is registered for this field. + * @return the refined {@link RuntimeHints} predicate + * @since 7.0 + */ + public FieldHintPredicate invocation() { + this.executableMode = ExecutableMode.INVOKE; + return this; + } + @Override public boolean test(RuntimeHints runtimeHints) { TypeHint typeHint = runtimeHints.reflection().getTypeHint(this.field.getDeclaringClass()); - if (typeHint == null) { - return false; + if (typeHint != null) { + if (this.executableMode == ExecutableMode.INVOKE) { + if (Modifier.isPublic(this.field.getModifiers())) { + return typeHint.getMemberCategories().contains(MemberCategory.INVOKE_PUBLIC_FIELDS); + } + else { + return typeHint.getMemberCategories().contains(MemberCategory.INVOKE_DECLARED_FIELDS); + } + } + else { + return true; + } } - return memberCategoryMatch(typeHint) || exactMatch(typeHint); - } - - private boolean memberCategoryMatch(TypeHint typeHint) { - if (Modifier.isPublic(this.field.getModifiers())) { - return typeHint.getMemberCategories().contains(MemberCategory.PUBLIC_FIELDS); - } - else { - return typeHint.getMemberCategories().contains(MemberCategory.DECLARED_FIELDS); - } - } - - private boolean exactMatch(TypeHint typeHint) { - return typeHint.fields().anyMatch(fieldHint -> - this.field.getName().equals(fieldHint.getName())); + return false; } } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ResourceHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ResourceHintsPredicates.java index d59d48af6c..3023546943 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ResourceHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ResourceHintsPredicates.java @@ -19,14 +19,13 @@ package org.springframework.aot.hint.predicate; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; -import java.util.regex.Pattern; import org.springframework.aot.hint.ResourceHints; import org.springframework.aot.hint.ResourcePatternHint; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; +import org.springframework.util.AntPathMatcher; import org.springframework.util.Assert; -import org.springframework.util.ConcurrentLruCache; /** * Generator of {@link ResourceHints} predicates, testing whether the given hints @@ -39,7 +38,7 @@ import org.springframework.util.ConcurrentLruCache; */ public class ResourceHintsPredicates { - private static final ConcurrentLruCache CACHED_RESOURCE_PATTERNS = new ConcurrentLruCache<>(32, ResourcePatternHint::toRegex); + private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher(); ResourceHintsPredicates() { } @@ -100,26 +99,18 @@ public class ResourceHintsPredicates { return hints -> { AggregatedResourcePatternHints aggregatedResourcePatternHints = AggregatedResourcePatternHints.of( hints.resources()); - boolean isExcluded = aggregatedResourcePatternHints.excludes().stream().anyMatch(excluded -> - CACHED_RESOURCE_PATTERNS.get(excluded).matcher(resourceNameToUse).matches()); - if (isExcluded) { - return false; - } return aggregatedResourcePatternHints.includes().stream().anyMatch(included -> - CACHED_RESOURCE_PATTERNS.get(included).matcher(resourceNameToUse).matches()); + PATH_MATCHER.match(included.getPattern(), resourceNameToUse)); }; } - private record AggregatedResourcePatternHints(List includes, List excludes) { + private record AggregatedResourcePatternHints(List includes) { static AggregatedResourcePatternHints of(ResourceHints resourceHints) { List includes = new ArrayList<>(); - List excludes = new ArrayList<>(); - resourceHints.resourcePatternHints().forEach(resourcePatternHint -> { - includes.addAll(resourcePatternHint.getIncludes()); - excludes.addAll(resourcePatternHint.getExcludes()); - }); - return new AggregatedResourcePatternHints(includes, excludes); + resourceHints.resourcePatternHints().forEach(resourcePatternHint -> + includes.addAll(resourcePatternHint.getIncludes())); + return new AggregatedResourcePatternHints(includes); } } diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ExecutableHintTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ExecutableHintTests.java index f817ba56b8..978934af79 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ExecutableHintTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ExecutableHintTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Phillip Webb * @since 6.0 */ +@SuppressWarnings("removal") class ExecutableHintTests { @Test diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ExecutableModeTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ExecutableModeTests.java index d19df791de..ec16727bb9 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ExecutableModeTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ExecutableModeTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Stephane Nicoll */ +@SuppressWarnings("removal") class ExecutableModeTests { @Test diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java index 5e4c3cc14f..7756980bdb 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.verifyNoInteractions; * @author Stephane Nicoll * @author Sebastien Deleuze */ +@SuppressWarnings("removal") class ReflectionHintsTests { private final ReflectionHints reflectionHints = new ReflectionHints(); diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java index b8393dd52b..19e57e873b 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java @@ -117,7 +117,7 @@ class ResourceHintsTests { @Test void registerPatternWithIncludesAndExcludes() { this.resourceHints.registerPattern(resourceHint -> - resourceHint.includes("com/example/*.properties").excludes("com/example/to-ignore.properties")); + resourceHint.includes("com/example/*.properties")); assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies(patternOf( List.of("/", "com", "com/example", "com/example/*.properties"), List.of("com/example/to-ignore.properties"))); @@ -198,10 +198,7 @@ class ResourceHintsTests { } private Consumer patternOf(List includes, List excludes) { - return pattern -> { - assertThat(pattern.getIncludes()).map(ResourcePatternHint::getPattern).containsExactlyInAnyOrderElementsOf(includes); - assertThat(pattern.getExcludes()).map(ResourcePatternHint::getPattern).containsExactlyElementsOf(excludes); - }; + return pattern -> assertThat(pattern.getIncludes()).map(ResourcePatternHint::getPattern).containsExactlyInAnyOrderElementsOf(includes); } static class Nested { diff --git a/spring-core/src/test/java/org/springframework/aot/hint/RuntimeHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/RuntimeHintsTests.java index f88170d287..1778a82f03 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/RuntimeHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/RuntimeHintsTests.java @@ -47,11 +47,9 @@ class RuntimeHintsTests { @Test void resourceHintWithClass() { this.hints.resources().registerType(String.class); - assertThat(this.hints.resources().resourcePatternHints()).singleElement().satisfies(resourceHint -> { - assertThat(resourceHint.getIncludes()).map(ResourcePatternHint::getPattern) - .containsExactlyInAnyOrder("/", "java", "java/lang", "java/lang/String.class"); - assertThat(resourceHint.getExcludes()).isEmpty(); - }); + assertThat(this.hints.resources().resourcePatternHints()).singleElement().satisfies(resourceHint -> + assertThat(resourceHint.getIncludes()).map(ResourcePatternHint::getPattern) + .containsExactlyInAnyOrder("/", "java", "java/lang", "java/lang/String.class")); } @Test 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 5c84ec93bb..4aa0f6b97a 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 @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException * * @author Stephane Nicoll */ +@SuppressWarnings("removal") class TypeHintTests { @Test @@ -169,9 +170,8 @@ class TypeHintTests { void builtWithAppliesMemberCategories() { TypeHint.Builder builder = new TypeHint.Builder(TypeReference.of(String.class)); assertThat(builder.build().getMemberCategories()).isEmpty(); - TypeHint.builtWith(MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS).accept(builder); - assertThat(builder.build().getMemberCategories()).containsExactlyInAnyOrder(MemberCategory.DECLARED_CLASSES, - MemberCategory.DECLARED_FIELDS); + TypeHint.builtWith(MemberCategory.DECLARED_FIELDS).accept(builder); + assertThat(builder.build().getMemberCategories()).containsExactly(MemberCategory.DECLARED_FIELDS); } } 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 896da82a60..3ba1db988a 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * * @author Brian Clozel */ +@SuppressWarnings("removal") class ReflectionHintsPredicatesTests { private static Constructor privateConstructor; @@ -160,6 +161,12 @@ class ReflectionHintsPredicatesTests { assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).introspect()); } + @Test + void constructorIntrospectionMatchesTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); + assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); + } + @Test void constructorIntrospectionMatchesConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> @@ -230,22 +237,16 @@ class ReflectionHintsPredicatesTests { } @Test - void privateConstructorIntrospectionMatchesConstructorHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); + void privateConstructorIntrospectionMatchesTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect()); } @Test - void privateConstructorIntrospectionDoesNotMatchIntrospectPublicConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); - assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).introspect()); - } - - @Test - void privateConstructorIntrospectionDoesNotMatchInvokePublicConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS); - assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).introspect()); + void privateConstructorIntrospectionMatchesConstructorHint() { + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); + assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect()); } @Test @@ -303,6 +304,12 @@ class ReflectionHintsPredicatesTests { @Nested class ReflectionOnMethod { + @Test + void methodIntrospectionMatchesTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); + assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); + } + @Test void methodIntrospectionMatchesMethodHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> @@ -328,18 +335,6 @@ class ReflectionHintsPredicatesTests { assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); } - @Test - void methodIntrospectionDoesNotMatchIntrospectDeclaredMethods() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_DECLARED_METHODS); - assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); - } - - @Test - void methodIntrospectionDoesNotMatchInvokeDeclaredMethods() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_METHODS); - assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); - } - @Test void methodInvocationDoesNotMatchMethodHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> @@ -379,22 +374,16 @@ class ReflectionHintsPredicatesTests { } @Test - void privateMethodIntrospectionMatchesMethodHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT)); + void privateMethodIntrospectionMatchesTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").introspect()); } @Test - void privateMethodIntrospectionDoesNotMatchIntrospectPublicMethods() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_METHODS); - assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "privateMethod").introspect()); - } - - @Test - void privateMethodIntrospectionDoesNotMatchInvokePublicMethods() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_METHODS); - assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "privateMethod").introspect()); + void privateMethodIntrospectionMatchesMethodHint() { + runtimeHints.reflection().registerType(SampleClass.class, typeHint -> + typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT)); + assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").introspect()); } @Test @@ -464,15 +453,15 @@ class ReflectionHintsPredicatesTests { } @Test - void fieldReflectionMatchesFieldHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField")); + void fieldReflectionMatchesTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); assertPredicateMatches(reflection.onField(SampleClass.class, "publicField")); } @Test - void fieldReflectionDoesNotMatchNonRegisteredFielddHint() { + void fieldReflectionMatchesFieldHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField")); - assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "privateField")); + assertPredicateMatches(reflection.onField(SampleClass.class, "publicField")); } @Test @@ -482,9 +471,21 @@ class ReflectionHintsPredicatesTests { } @Test - void fieldReflectionDoesNotMatchDeclaredFieldsHint() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.DECLARED_FIELDS); - assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField")); + void fieldInvocationMatchesPublicFieldsHint() { + runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_FIELDS); + assertPredicateMatches(reflection.onField(SampleClass.class, "publicField").invocation()); + } + + @Test + void fieldInvocationDoesNotMatchTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); + assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField").invocation()); + } + + @Test + void privateFieldReflectionMatchesTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); + assertPredicateMatches(reflection.onField(SampleClass.class, "privateField")); } @Test @@ -493,18 +494,24 @@ class ReflectionHintsPredicatesTests { assertPredicateMatches(reflection.onField(SampleClass.class, "privateField")); } - @Test - void privateFieldReflectionDoesNotMatchPublicFieldsHint() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.PUBLIC_FIELDS); - assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "privateField")); - } - @Test void privateFieldReflectionMatchesDeclaredFieldsHint() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.DECLARED_FIELDS); assertPredicateMatches(reflection.onField(SampleClass.class, "privateField")); } + @Test + void privateFieldInvocationMatchesDeclaredFieldsHint() { + runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_FIELDS); + assertPredicateMatches(reflection.onField(SampleClass.class, "privateField").invocation()); + } + + @Test + void privateFieldInvocationDoesNotMatchTypeHint() { + runtimeHints.reflection().registerType(SampleClass.class); + assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "privateField").invocation()); + } + } private void assertPredicateMatches(Predicate predicate) { diff --git a/spring-core/src/test/java/org/springframework/aot/hint/support/FilePatternResourceHintsRegistrarTests.java b/spring-core/src/test/java/org/springframework/aot/hint/support/FilePatternResourceHintsRegistrarTests.java index c34af38671..a8c93b1ec9 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/support/FilePatternResourceHintsRegistrarTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/support/FilePatternResourceHintsRegistrarTests.java @@ -140,11 +140,8 @@ class FilePatternResourceHintsRegistrarTests { } private Consumer includes(String... patterns) { - return hint -> { - assertThat(hint.getIncludes().stream().map(ResourcePatternHint::getPattern)) - .containsExactlyInAnyOrder(patterns); - assertThat(hint.getExcludes()).isEmpty(); - }; + return hint -> assertThat(hint.getIncludes().stream().map(ResourcePatternHint::getPattern)) + .containsExactlyInAnyOrder(patterns); } }