Fix AOT code generation for managed types.
Closes #2704 Original pull request: #2705.
This commit is contained in:
committed by
Mark Paluch
parent
b55f098b43
commit
1fde452ab9
@@ -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");
|
||||
|
||||
@@ -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<ManagedTypes> 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<Class<?>> action) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class StoreManagedTypesWithCustomFactoryMethod implements ManagedTypes {
|
||||
|
||||
private ManagedTypes source;
|
||||
|
||||
Reference in New Issue
Block a user