From 2d7fba5e50825692c0a4e526a77b9fce49a00066 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 8 Sep 2025 10:34:16 +0200 Subject: [PATCH] Polishing. Encapsulate config, add details about ant-path-style matching. Original Pull Request: #3318 --- src/main/antora/modules/ROOT/pages/aot.adoc | 26 ++++---- .../data/aot/DefaultAotContext.java | 60 +++++++++++++++---- 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/main/antora/modules/ROOT/pages/aot.adoc b/src/main/antora/modules/ROOT/pages/aot.adoc index 60d02d77c..f60d10ece 100644 --- a/src/main/antora/modules/ROOT/pages/aot.adoc +++ b/src/main/antora/modules/ROOT/pages/aot.adoc @@ -23,24 +23,28 @@ If Ahead of Time compilation is enabled Spring Data can (depending on the actual * Repository Metadata in JSON format Each of the above is enabled by default. -However there users may fine tune the configuration with following options. +However, there users may fine tune the configuration with following options. [options = "autowidth",cols="1,1"] |=== -|spring.aot.data.accessors.enabled -|boolean flag to control contribution of Bytecode for generated Type/Property Accessors +|`spring.aot.data.accessors.enabled` +|Boolean flag to control contribution of Bytecode for generated Type/Property Accessors -|spring.aot.data.accessors.exclude -|comma separated list of FQCN for which to skip contribution of Bytecode for generated Type/Property Accessors +|`spring.aot.data.accessors.include` +|Comma separated list of FQCN for which to contribute Bytecode for generated Type/Property Accessors. +Ant-style include patterns matching package names (e.g. `com.acme.**`) or type names inclusion. +Inclusion pattern matches are evaluated before exclusions for broad exclusion and selective inclusion. -|spring.aot.data.accessors.include -|comma separated list of FQCN for which to contribute Bytecode for generated Type/Property Accessors +|`spring.aot.data.accessors.exclude` +|Comma separated list of FQCN for which to skip contribution of Bytecode for generated Type/Property Accessors. +Ant-style exclude patterns matching package names (e.g. `com.acme.**`) or type names exclusion. +Exclusion pattern matches are evaluated after inclusions for broad exclusion and selective inclusion. -|spring.aot.repositories.enabled -|boolean flag to control contribution of Source Code for Repository Interfaces +|`spring.aot.repositories.enabled` +|Boolean flag to control contribution of Source Code for Repository Interfaces -|spring.aot.[module-name].repositories.enabled -|boolean flag to control contribution of Source Code for Repository Interfaces for a certain module (eg. jdbc) +|`spring.aot.[module-name].repositories.enabled` +|Boolean flag to control contribution of Source Code for Repository Interfaces for a certain module (eg. `jdbc`, `jpa`, `mongodb`, `cassandra`) |=== [[aot.repositories]] diff --git a/src/main/java/org/springframework/data/aot/DefaultAotContext.java b/src/main/java/org/springframework/data/aot/DefaultAotContext.java index f2e6bb26d..fcffdaa0a 100644 --- a/src/main/java/org/springframework/data/aot/DefaultAotContext.java +++ b/src/main/java/org/springframework/data/aot/DefaultAotContext.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.stream.Stream; import org.jspecify.annotations.Nullable; @@ -39,6 +40,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.env.Environment; +import org.springframework.data.util.Lazy; import org.springframework.data.util.QTypeContributor; import org.springframework.data.util.TypeContributor; import org.springframework.util.AntPathMatcher; @@ -234,11 +236,8 @@ class DefaultAotContext implements AotContext { if (contributeAccessors) { - boolean accessorsEnabled = environment.getProperty("spring.aot.data.accessors.enabled", Boolean.class, true); - String include = environment.getProperty("spring.aot.data.accessors.include", String.class, ""); - String exclude = environment.getProperty("spring.aot.data.accessors.exclude", String.class, ""); - - if (shouldContributeAccessors(type, accessorsEnabled, include, exclude)) { + AccessorContributionConfiguration configuration = AccessorContributionConfiguration.of(environment); + if (configuration.shouldContributeAccessors(type)) { mappingContext.contribute(type); } } @@ -257,20 +256,55 @@ class DefaultAotContext implements AotContext { Stream.concat(Stream.of(TypeReference.of(type)), proxyInterfaces.stream()).toArray(TypeReference[]::new)); } } + } + } + + /** + * Configuration for accessor to determine whether accessors should be contributed for a given type. + */ + private record AccessorContributionConfiguration(boolean enabled, Lazy include, Lazy exclude) { + + /** + * {@code boolean }Environment property to enable/disable accessor contribution. Enabled by default. + */ + public static final String ACCESSORS_ENABLED = "spring.aot.data.accessors.enabled"; + + /** + * {@code String} Environment property to define Ant-style include patterns (comma-separated) matching package names + * (e.g. {@code com.acme.**}) or type names inclusion. Inclusion pattern matches are evaluated before exclusions for + * broad exclusion and selective inclusion. + */ + public static final String INCLUDE_PATTERNS = "spring.aot.data.accessors.include"; + + /** + * {@code String} Environment property to define Ant-style exclude patterns (comma-separated) matching package names + * (e.g. {@code com.acme.**}) or type names exclusion. Exclusion pattern matches are evaluated after inclusions for + * broad exclusion and selective inclusion. + */ + public static final String EXCLUDE_PATTERNS = "spring.aot.data.accessors.exclude"; + + private static final AntPathMatcher antPathMatcher = new AntPathMatcher("."); + + private AccessorContributionConfiguration(boolean enabled, Supplier include, Supplier exclude) { + this(enabled, Lazy.of(include), Lazy.of(exclude)); } - static boolean shouldContributeAccessors(Class type, boolean enabled, String include, String exclude) { + public static AccessorContributionConfiguration of(Environment environment) { + return new AccessorContributionConfiguration(environment.getProperty(ACCESSORS_ENABLED, Boolean.class, true), + () -> environment.getProperty(INCLUDE_PATTERNS, String.class, ""), + () -> environment.getProperty(EXCLUDE_PATTERNS, String.class, "")); + } + + boolean shouldContributeAccessors(Class type) { if (!enabled) { return false; } - AntPathMatcher antPathMatcher = new AntPathMatcher("."); - - if (StringUtils.hasText(include)) { + if (StringUtils.hasText(include.get())) { - String[] includes = include.split(","); + String[] includes = include.get().split(","); for (String includePattern : includes) { if (antPathMatcher.match(includePattern.trim(), type.getName())) { @@ -279,9 +313,9 @@ class DefaultAotContext implements AotContext { } } - if (StringUtils.hasText(exclude)) { + if (StringUtils.hasText(exclude.get())) { - String[] excludes = exclude.split(","); + String[] excludes = exclude.get().split(","); for (String excludePattern : excludes) { if (antPathMatcher.match(excludePattern.trim(), type.getName())) { @@ -292,5 +326,7 @@ class DefaultAotContext implements AotContext { return true; } + } + }