diff --git a/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java b/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java index ec1f277aa..5bc669967 100644 --- a/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java +++ b/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java @@ -17,6 +17,7 @@ package org.springframework.data.aot; import java.lang.reflect.Executable; import java.lang.reflect.Method; +import java.util.Collections; import java.util.List; import java.util.function.BiConsumer; @@ -34,9 +35,12 @@ import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.core.ResolvableType; import org.springframework.data.domain.ManagedTypes; import org.springframework.data.util.Lazy; +import org.springframework.javapoet.ClassName; import org.springframework.javapoet.CodeBlock; import org.springframework.javapoet.MethodSpec.Builder; import org.springframework.javapoet.ParameterizedTypeName; +import org.springframework.javapoet.TypeName; +import org.springframework.javapoet.WildcardTypeName; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -167,7 +171,15 @@ class ManagedTypesRegistrationAotContribution implements RegisteredBeanAotContri CodeBlock.Builder builder = CodeBlock.builder().add("return ").beginControlFlow("(registeredBean -> "); - builder.addStatement("var types = $T.of($L)", List.class, toCodeBlock(sourceTypes, allSourceTypesVisible)); + if(sourceTypes.isEmpty()) { + + TypeName wildcard = WildcardTypeName.subtypeOf(Object.class); + TypeName classOfAny = ParameterizedTypeName.get(ClassName.get(Class.class), wildcard); + + builder.addStatement("var types = $T.<$T>emptyList()", Collections.class, classOfAny); + } else { + builder.addStatement("var types = $T.of($L)", List.class, toCodeBlock(sourceTypes, allSourceTypesVisible)); + } if (allSourceTypesVisible) { builder.addStatement("var managedTypes = $T.fromIterable($L)", ManagedTypes.class, "types"); diff --git a/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java b/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java index bbb2efea8..f1916654b 100644 --- a/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java +++ b/src/test/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessorUnitTests.java @@ -195,6 +195,28 @@ class ManagedTypesBeanRegistrationAotProcessorUnitTests { }); } + @Test // GH-2680 + void generatesInstanceSupplierCodeFragmentToAvoidDuplicateInvocationsForEmptyManagedTypes() { + + beanFactory.registerBeanDefinition("commons.managed-types", BeanDefinitionBuilder.rootBeanDefinition(EmptyManagedTypes.class).getBeanDefinition()); + RegisteredBean registeredBean = RegisteredBean.of(beanFactory, "commons.managed-types"); + + BeanRegistrationAotContribution contribution = createPostProcessor("commons") + .processAheadOfTime(RegisteredBean.of(beanFactory, "commons.managed-types")); + + AotTestCodeContributionBuilder.withContextFor(this.getClass()).writeContentFor(contribution).compile(it -> { + + + InstanceSupplier types = ReflectionTestUtils + .invokeMethod(it.getAllCompiledClasses().iterator().next(), "instance"); + try { + assertThat(types.get(registeredBean).toList()).isEmpty(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + @Test // GH-2680 void generatesInstanceSupplierCodeFragmentForTypeWithCustomFactoryMethod() { @@ -269,6 +291,22 @@ class ManagedTypesBeanRegistrationAotProcessorUnitTests { } } + public static class EmptyManagedTypes implements ManagedTypes { + + public EmptyManagedTypes() { + + } + + public static EmptyManagedTypes of(ManagedTypes source) { + return new EmptyManagedTypes(); + } + + @Override + public void forEach(Consumer> action) { + + } + } + public static class StoreManagedTypesWithCustomFactoryMethod implements ManagedTypes { private ManagedTypes source;