From 1fde452ab95c97837454d236b20e991217868d4f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 10 Oct 2022 09:22:41 +0200 Subject: [PATCH] Fix AOT code generation for managed types. Closes #2704 Original pull request: #2705. --- ...nagedTypesRegistrationAotContribution.java | 14 ++++++- ...BeanRegistrationAotProcessorUnitTests.java | 38 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) 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;