Add AOT support for TypedStringValue
This commit adds support for TypeStringValue when generating AOT code. If the value does not specify an explicit type, it's specified as is. Otherwise, the TypeStringValue instance is restored via the appropriate code generation. Closes gh-29074
This commit is contained in:
committed by
Stéphane Nicoll
parent
15c19411f6
commit
37c2619fc4
@@ -52,6 +52,8 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.testfixture.beans.Employee;
|
||||
import org.springframework.beans.testfixture.beans.Pet;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy.Implementation;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy.One;
|
||||
@@ -62,6 +64,7 @@ import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
|
||||
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
import org.springframework.context.testfixture.context.annotation.AutowiredComponent;
|
||||
import org.springframework.context.testfixture.context.annotation.AutowiredGenericTemplate;
|
||||
import org.springframework.context.testfixture.context.annotation.CglibConfiguration;
|
||||
@@ -79,6 +82,7 @@ import org.springframework.context.testfixture.context.generator.SimpleComponent
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.test.tools.CompileWithForkedClassLoader;
|
||||
import org.springframework.core.test.tools.Compiled;
|
||||
@@ -441,6 +445,59 @@ class ApplicationContextAotGeneratorTests {
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class XmlSupport {
|
||||
|
||||
@Test
|
||||
void processAheadOfTimeWhenHasTypedStringValue() {
|
||||
GenericXmlApplicationContext applicationContext = new GenericXmlApplicationContext();
|
||||
applicationContext
|
||||
.load(new ClassPathResource("applicationContextAotGeneratorTests-values.xml", getClass()));
|
||||
testCompiledResult(applicationContext, (initializer, compiled) -> {
|
||||
GenericApplicationContext freshApplicationContext = toFreshApplicationContext(initializer);
|
||||
Employee employee = freshApplicationContext.getBean(Employee.class);
|
||||
assertThat(employee.getName()).isEqualTo("John Smith");
|
||||
assertThat(employee.getAge()).isEqualTo(42);
|
||||
assertThat(employee.getCompany()).isEqualTo("Acme Widgets, Inc.");
|
||||
assertThat(freshApplicationContext.getBean("pet", Pet.class)
|
||||
.getName()).isEqualTo("Fido");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void processAheadOfTimeWhenHasTypedStringValueWithType() {
|
||||
GenericXmlApplicationContext applicationContext = new GenericXmlApplicationContext();
|
||||
applicationContext
|
||||
.load(new ClassPathResource("applicationContextAotGeneratorTests-values-types.xml", getClass()));
|
||||
testCompiledResult(applicationContext, (initializer, compiled) -> {
|
||||
GenericApplicationContext freshApplicationContext = toFreshApplicationContext(initializer);
|
||||
Employee employee = freshApplicationContext.getBean(Employee.class);
|
||||
assertThat(employee.getName()).isEqualTo("John Smith");
|
||||
assertThat(employee.getAge()).isEqualTo(42);
|
||||
assertThat(employee.getCompany()).isEqualTo("Acme Widgets, Inc.");
|
||||
assertThat(compiled.getSourceFile(".*Employee__BeanDefinitions"))
|
||||
.contains("new TypedStringValue(\"42\", Integer.class");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void processAheadOfTimeWhenHasTypedStringValueWithExpression() {
|
||||
GenericXmlApplicationContext applicationContext = new GenericXmlApplicationContext();
|
||||
applicationContext
|
||||
.load(new ClassPathResource("applicationContextAotGeneratorTests-values-expressions.xml", getClass()));
|
||||
testCompiledResult(applicationContext, (initializer, compiled) -> {
|
||||
GenericApplicationContext freshApplicationContext = toFreshApplicationContext(initializer);
|
||||
Employee employee = freshApplicationContext.getBean(Employee.class);
|
||||
assertThat(employee.getName()).isEqualTo("John Smith");
|
||||
assertThat(employee.getAge()).isEqualTo(42);
|
||||
assertThat(employee.getCompany()).isEqualTo("Acme Widgets, Inc.");
|
||||
assertThat(freshApplicationContext.getBean("pet", Pet.class)
|
||||
.getName()).isEqualTo("Fido");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Consumer<List<? extends JdkProxyHint>> doesNotHaveProxyFor(Class<?> target) {
|
||||
return hints -> assertThat(hints).noneMatch(hint ->
|
||||
hint.getProxiedInterfaces().get(0).equals(TypeReference.of(target)));
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
@@ -362,6 +363,34 @@ class GenericApplicationContextTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshForAotLoadsTypedStringValueClassNameInProperty() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition("java.lang.Integer");
|
||||
beanDefinition.getPropertyValues().add("value", new TypedStringValue("42", "java.lang.Integer"));
|
||||
context.registerBeanDefinition("number", beanDefinition);
|
||||
context.refreshForAotProcessing(new RuntimeHints());
|
||||
assertThat(getBeanDefinition(context, "number").getPropertyValues().get("value"))
|
||||
.isInstanceOfSatisfying(TypedStringValue.class, typeStringValue ->
|
||||
assertThat(typeStringValue.getTargetType()).isEqualTo(Integer.class));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshForAotLoadsTypedStringValueClassNameInConstructorArgument() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition("java.lang.Integer");
|
||||
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,
|
||||
new TypedStringValue("42", "java.lang.Integer"));
|
||||
context.registerBeanDefinition("number", beanDefinition);
|
||||
context.refreshForAotProcessing(new RuntimeHints());
|
||||
assertThat(getBeanDefinition(context, "number").getConstructorArgumentValues()
|
||||
.getIndexedArgumentValue(0, TypedStringValue.class).getValue())
|
||||
.isInstanceOfSatisfying(TypedStringValue.class, typeStringValue ->
|
||||
assertThat(typeStringValue.getTargetType()).isEqualTo(Integer.class));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshForAotInvokesBeanFactoryPostProcessors() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
||||
Reference in New Issue
Block a user