From 5aa7f583d5cdf2bf55eee55df1349fb20e4eab0f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 26 Nov 2025 11:07:21 +0100 Subject: [PATCH 1/2] Prepare issue branch. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 253b26b609..ab382d24dc 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-commons - 4.1.0-SNAPSHOT + 4.1.x-GH-3414-SNAPSHOT Spring Data Core Core Spring concepts underpinning every Spring Data module. From c63d72bb86f333c29d978da8df346a891b1be131 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 26 Nov 2025 11:52:32 +0100 Subject: [PATCH 2/2] Retrieve Environment from RegisteredBean. --- ...agedTypesBeanRegistrationAotProcessor.java | 26 ++++++++++-- ...BeanRegistrationAotProcessorUnitTests.java | 40 ++++++++++++++++++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java b/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java index 2e978a3c1f..e8d5dadd0a 100644 --- a/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java +++ b/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java @@ -33,6 +33,7 @@ import org.springframework.context.EnvironmentAware; import org.springframework.core.ResolvableType; import org.springframework.core.env.Environment; +import org.springframework.core.env.EnvironmentCapable; import org.springframework.core.env.StandardEnvironment; import org.springframework.data.domain.ManagedTypes; import org.springframework.data.util.Lazy; @@ -40,6 +41,7 @@ import org.springframework.data.util.TypeContributor; import org.springframework.data.util.TypeUtils; import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -54,7 +56,8 @@ public class ManagedTypesBeanRegistrationAotProcessor implements BeanRegistratio private final Log logger = LogFactory.getLog(getClass()); private @Nullable String moduleIdentifier; - private Lazy environment = Lazy.of(StandardEnvironment::new); + private static final Lazy DEFAULT_ENVIRONMENT = Lazy.of(StandardEnvironment::new); + private @Nullable Environment environment = null; public void setModuleIdentifier(@Nullable String moduleIdentifier) { this.moduleIdentifier = moduleIdentifier; @@ -67,7 +70,7 @@ public String getModuleIdentifier() { @Override public void setEnvironment(Environment environment) { - this.environment = Lazy.of(environment); + this.environment = environment; } @Override @@ -77,7 +80,7 @@ public void setEnvironment(Environment environment) { return null; } - DefaultAotContext aotContext = new DefaultAotContext(registeredBean.getBeanFactory(), environment.get()); + DefaultAotContext aotContext = new DefaultAotContext(registeredBean.getBeanFactory(), getConfiguredEnvironmentOrTryToResolveOne(registeredBean)); return contribute(aotContext, resolveManagedTypes(registeredBean), registeredBean); } @@ -183,4 +186,21 @@ protected boolean matchesByType(@Nullable Class beanType) { protected boolean matchesPrefix(@Nullable String beanName) { return StringUtils.startsWithIgnoreCase(beanName, getModuleIdentifier()); } + + protected Environment getConfiguredEnvironmentOrTryToResolveOne(RegisteredBean registeredBean) { + + if (this.environment != null) { + return this.environment; + } + + if (registeredBean.getBeanFactory() instanceof EnvironmentCapable ec) { + return ec.getEnvironment(); + } else { + String[] beanNamesForType = registeredBean.getBeanFactory().getBeanNamesForType(Environment.class); + if (!ObjectUtils.isEmpty(beanNamesForType)) { + return registeredBean.getBeanFactory().getBean(beanNamesForType[0], Environment.class); + } + } + return DEFAULT_ENVIRONMENT.get(); + } } diff --git a/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java b/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java index 46dc856877..207a76e1d6 100644 --- a/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java +++ b/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java @@ -41,10 +41,12 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.data.aot.ManagedTypesRegistrationAotContribution.ManagedTypesInstanceCodeFragment; import org.springframework.data.domain.ManagedTypes; import org.springframework.javapoet.MethodSpec; import org.springframework.javapoet.MethodSpec.Builder; +import org.springframework.mock.env.MockEnvironment; import org.springframework.test.util.ReflectionTestUtils; /** @@ -198,7 +200,8 @@ void generatesInstanceSupplierCodeFragmentToAvoidDuplicateInvocations() { @Test // GH-2680 void generatesInstanceSupplierCodeFragmentToAvoidDuplicateInvocationsForEmptyManagedTypes() { - beanFactory.registerBeanDefinition("commons.managed-types", BeanDefinitionBuilder.rootBeanDefinition(EmptyManagedTypes.class).getBeanDefinition()); + beanFactory.registerBeanDefinition("commons.managed-types", + BeanDefinitionBuilder.rootBeanDefinition(EmptyManagedTypes.class).getBeanDefinition()); RegisteredBean registeredBean = RegisteredBean.of(beanFactory, "commons.managed-types"); BeanRegistrationAotContribution contribution = createPostProcessor("commons") @@ -206,7 +209,6 @@ void generatesInstanceSupplierCodeFragmentToAvoidDuplicateInvocationsForEmptyMan AotTestCodeContributionBuilder.withContextFor(this.getClass()).writeContentFor(contribution).compile(it -> { - InstanceSupplier types = ReflectionTestUtils .invokeMethod(it.getAllCompiledClasses().iterator().next(), "instance"); try { @@ -266,6 +268,40 @@ void canGenerateCodeReturnsFalseIfNoFactoryMethodPresent() { assertThat(fragment.canGenerateCode()).isFalse(); } + @Test // GH-3414 + void usesConfiguredEnvironment() { + + MockEnvironment env = spy(new MockEnvironment()); + ManagedTypesBeanRegistrationAotProcessor processor = createPostProcessor("commons"); + processor.setEnvironment(env); + + beanFactory.registerBeanDefinition("commons.managed-types", managedTypesDefinition); + + BeanRegistrationAotContribution contribution = processor + .processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types")); + + contribution.applyTo(new TestGenerationContext(Object.class), null); + + verify(env).getProperty(eq("spring.aot.data.accessors.enabled"), eq(Boolean.class), eq(true)); + } + + @Test // GH-3414 + void usesUsesEnvironmentFromBeanIfNotSet() { + + MockEnvironment env = spy(new MockEnvironment()); + ManagedTypesBeanRegistrationAotProcessor processor = createPostProcessor("commons"); + + beanFactory.registerBeanDefinition("commons.managed-types", managedTypesDefinition); + beanFactory.registerBeanDefinition("environment", new RootBeanDefinition(Environment.class, () -> env)); + + BeanRegistrationAotContribution contribution = processor + .processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types")); + + contribution.applyTo(new TestGenerationContext(Object.class), null); + + verify(env).getProperty(eq("spring.aot.data.accessors.enabled"), eq(Boolean.class), eq(true)); + } + private ManagedTypesBeanRegistrationAotProcessor createPostProcessor(String moduleIdentifier) { ManagedTypesBeanRegistrationAotProcessor postProcessor = new ManagedTypesBeanRegistrationAotProcessor(); postProcessor.setModuleIdentifier(moduleIdentifier);