diff --git a/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHintsPredicates.java index c74cb78501..36648680dc 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/ReflectionHintsPredicates.java @@ -36,6 +36,7 @@ import org.springframework.util.ReflectionUtils; * match the expected behavior for reflection. * * @author Brian Clozel + * @author Stephane Nicoll * @since 6.0 */ public class ReflectionHintsPredicates { @@ -248,15 +249,17 @@ public class ReflectionHintsPredicates { abstract Predicate exactMatch(); /** - * Indicate whether the first {@code ExecutableHint} covers the reflection needs for the other one. - * For that, both hints must apply to the same member (same type, name and parameters) - * and the configured {@code ExecutableMode} of the first must cover the second. + * Indicate whether the specified {@code ExecutableHint} covers the + * reflection needs of the specified executable definition. + * @return {@code true} if the member matches (same type, name and parameters), + * and the configured {@code ExecutableMode} is compatibe */ - static boolean includes(ExecutableHint hint, ExecutableHint other) { - return hint.getName().equals(other.getName()) - && hint.getParameterTypes().equals(other.getParameterTypes()) + static boolean includes(ExecutableHint hint, String name, + List parameterTypes, List executableModes) { + return hint.getName().equals(name) + && hint.getParameterTypes().equals(parameterTypes) && (hint.getModes().contains(ExecutableMode.INVOKE) - || !other.getModes().contains(ExecutableMode.INVOKE)); + || !executableModes.contains(ExecutableMode.INVOKE)); } } @@ -269,31 +272,32 @@ public class ReflectionHintsPredicates { @Override MemberCategory[] getPublicMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] {MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, - MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS}; + return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS }; } - return new MemberCategory[] {MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS}; + return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS }; } @Override MemberCategory[] getDeclaredMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] {MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, - MemberCategory.INVOKE_DECLARED_CONSTRUCTORS}; + return new MemberCategory[] { MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS }; } - return new MemberCategory[] {MemberCategory.INVOKE_DECLARED_CONSTRUCTORS}; + return new MemberCategory[] { MemberCategory.INVOKE_DECLARED_CONSTRUCTORS }; } @Override Predicate exactMatch() { return hints -> (hints.reflection().getTypeHint(this.executable.getDeclaringClass()) != null) && hints.reflection().getTypeHint(this.executable.getDeclaringClass()).constructors().anyMatch(executableHint -> { - List parameters = Arrays.stream(this.executable.getParameterTypes()).map(TypeReference::of).toList(); - ExecutableHint syntheticHint = ExecutableHint.ofConstructor(parameters) - .setModes(this.executableMode).build(); - return includes(executableHint, syntheticHint); - }); + List parameters = Arrays.stream(this.executable.getParameterTypes()) + .map(TypeReference::of).toList(); + return includes(executableHint, "", + parameters, List.of(this.executableMode)); + }); } + } public static class MethodHintPredicate extends ExecutableHintPredicate { @@ -306,32 +310,33 @@ public class ReflectionHintsPredicates { @Override MemberCategory[] getPublicMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] {MemberCategory.INTROSPECT_PUBLIC_METHODS, - MemberCategory.INVOKE_PUBLIC_METHODS}; + return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_METHODS, + MemberCategory.INVOKE_PUBLIC_METHODS }; } - return new MemberCategory[] {MemberCategory.INVOKE_PUBLIC_METHODS}; + return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_METHODS }; } @Override MemberCategory[] getDeclaredMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { - return new MemberCategory[] {MemberCategory.INTROSPECT_DECLARED_METHODS, - MemberCategory.INVOKE_DECLARED_METHODS}; + return new MemberCategory[] { MemberCategory.INTROSPECT_DECLARED_METHODS, + MemberCategory.INVOKE_DECLARED_METHODS }; } - return new MemberCategory[] {MemberCategory.INVOKE_DECLARED_METHODS}; + return new MemberCategory[] { MemberCategory.INVOKE_DECLARED_METHODS }; } @Override Predicate exactMatch() { return hints -> (hints.reflection().getTypeHint(this.executable.getDeclaringClass()) != null) && hints.reflection().getTypeHint(this.executable.getDeclaringClass()).methods().anyMatch(executableHint -> { - List parameters = Arrays.stream(this.executable.getParameterTypes()).map(TypeReference::of).toList(); - ExecutableHint syntheticHint = ExecutableHint.ofMethod(this.executable.getName(), parameters) - .setModes(this.executableMode).build(); - return includes(executableHint, syntheticHint); + List parameters = Arrays.stream(this.executable.getParameterTypes()) + .map(TypeReference::of).toList(); + return includes(executableHint, this.executable.getName(), + parameters, List.of(this.executableMode)); }); } + } public static class FieldHintPredicate implements Predicate { diff --git a/spring-core/src/main/java/org/springframework/aot/hint/ResourceHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/ResourceHintsPredicates.java index 09114250f2..3c65bb2e9d 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/ResourceHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/ResourceHintsPredicates.java @@ -16,6 +16,8 @@ package org.springframework.aot.hint; +import java.util.ArrayList; +import java.util.List; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -27,6 +29,7 @@ import org.springframework.util.ConcurrentLruCache; * match the expected behavior for resources. * * @author Brian Clozel + * @author Stephane Nicoll * @since 6.0 */ public class ResourceHintsPredicates { @@ -78,16 +81,31 @@ public class ResourceHintsPredicates { * @return the {@link RuntimeHints} predicate */ public Predicate forResource(String resourceName) { - return hints -> hints.resources().resourcePatterns().reduce(ResourcePatternHints::merge) - .map(hint -> { - boolean isExcluded = hint.getExcludes().stream() - .anyMatch(excluded -> CACHED_RESOURCE_PATTERNS.get(excluded).matcher(resourceName).matches()); - if (isExcluded) { - return false; - } - return hint.getIncludes().stream() - .anyMatch(included -> CACHED_RESOURCE_PATTERNS.get(included).matcher(resourceName).matches()); - }).orElse(false); + return hints -> { + AggregatedResourcePatternHints aggregatedResourcePatternHints = AggregatedResourcePatternHints.of( + hints.resources()); + boolean isExcluded = aggregatedResourcePatternHints.excludes().stream().anyMatch(excluded -> + CACHED_RESOURCE_PATTERNS.get(excluded).matcher(resourceName).matches()); + if (isExcluded) { + return false; + } + return aggregatedResourcePatternHints.includes().stream().anyMatch(included -> + CACHED_RESOURCE_PATTERNS.get(included).matcher(resourceName).matches()); + }; + } + + private record AggregatedResourcePatternHints(List includes, List excludes) { + + static AggregatedResourcePatternHints of(ResourceHints resourceHints) { + List includes = new ArrayList<>(); + List excludes = new ArrayList<>(); + resourceHints.resourcePatterns().forEach(resourcePatternHint -> { + includes.addAll(resourcePatternHint.getIncludes()); + excludes.addAll(resourcePatternHint.getExcludes()); + }); + return new AggregatedResourcePatternHints(includes, excludes); + } + } } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHints.java b/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHints.java index e3568c14f3..1dbd82cf8b 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHints.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHints.java @@ -45,11 +45,6 @@ public final class ResourcePatternHints { this.excludes = new ArrayList<>(builder.excludes); } - private ResourcePatternHints(List includes, List excludes) { - this.includes = includes; - this.excludes = excludes; - } - /** * Return the include patterns to use to identify the resources to match. * @return the include patterns @@ -66,16 +61,6 @@ public final class ResourcePatternHints { return this.excludes; } - ResourcePatternHints merge(ResourcePatternHints resourcePatternHints) { - List includes = new ArrayList<>(); - includes.addAll(this.includes); - includes.addAll(resourcePatternHints.includes); - List excludes = new ArrayList<>(); - excludes.addAll(this.excludes); - excludes.addAll(resourcePatternHints.excludes); - return new ResourcePatternHints(includes, excludes); - } - /** * Builder for {@link ResourcePatternHints}.