diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanBeanEarlyDeductionTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanEarlyDeductionTests.java similarity index 75% rename from spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanBeanEarlyDeductionTests.java rename to spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanEarlyDeductionTests.java index 1c5a4bb146..28a803f60a 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanBeanEarlyDeductionTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanEarlyDeductionTests.java @@ -29,7 +29,9 @@ import org.springframework.beans.factory.support.AbstractBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.ResolvableType; import org.springframework.core.type.AnnotationMetadata; import static org.assertj.core.api.Assertions.assertThat; @@ -39,8 +41,9 @@ import static org.assertj.core.api.Assertions.assertThat; * {@link FactoryBean FactoryBeans} defined in the configuration. * * @author Phillip Webb + * @author Juergen Hoeller */ -class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { +class ConfigurationWithFactoryBeanEarlyDeductionTests { @Test void preFreezeDirect() { @@ -82,6 +85,16 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { assertPostFreeze(AttributeClassConfiguration.class); } + @Test + void preFreezeTargetType() { + assertPreFreeze(TargetTypeConfiguration.class); + } + + @Test + void postFreezeTargetType() { + assertPostFreeze(TargetTypeConfiguration.class); + } + @Test void preFreezeUnresolvedGenericFactoryBean() { // Covers the case where a @Configuration is picked up via component scanning @@ -105,14 +118,13 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { } } + private void assertPostFreeze(Class configurationClass) { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - configurationClass); + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configurationClass); assertContainsMyBeanName(context); } - private void assertPreFreeze(Class configurationClass, - BeanFactoryPostProcessor... postProcessors) { + private void assertPreFreeze(Class configurationClass, BeanFactoryPostProcessor... postProcessors) { NameCollectingBeanFactoryPostProcessor postProcessor = new NameCollectingBeanFactoryPostProcessor(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); try (context) { @@ -132,41 +144,38 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { assertThat(names).containsExactly("myBean"); } - private static class NameCollectingBeanFactoryPostProcessor - implements BeanFactoryPostProcessor { + + private static class NameCollectingBeanFactoryPostProcessor implements BeanFactoryPostProcessor { private String[] names; @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) - throws BeansException { - this.names = beanFactory.getBeanNamesForType(MyBean.class, true, false); + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + ResolvableType typeToMatch = ResolvableType.forClassWithGenerics(MyBean.class, String.class); + this.names = beanFactory.getBeanNamesForType(typeToMatch, true, false); } public String[] getNames() { return this.names; } - } @Configuration static class DirectConfiguration { @Bean - MyBean myBean() { - return new MyBean(); + MyBean myBean() { + return new MyBean<>(); } - } @Configuration static class GenericMethodConfiguration { @Bean - FactoryBean myBean() { - return new TestFactoryBean<>(new MyBean()); + FactoryBean> myBean() { + return new TestFactoryBean<>(new MyBean<>()); } - } @Configuration @@ -176,13 +185,11 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { MyFactoryBean myBean() { return new MyFactoryBean(); } - } @Configuration @Import(AttributeClassRegistrar.class) static class AttributeClassConfiguration { - } static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar { @@ -191,16 +198,32 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition( RawWithAbstractObjectTypeFactoryBean.class).getBeanDefinition(); - definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, MyBean.class); + definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, + ResolvableType.forClassWithGenerics(MyBean.class, String.class)); registry.registerBeanDefinition("myBean", definition); } + } + @Configuration + @Import(TargetTypeRegistrar.class) + static class TargetTypeConfiguration { + } + + static class TargetTypeRegistrar implements ImportBeanDefinitionRegistrar { + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + RootBeanDefinition definition = new RootBeanDefinition(RawWithAbstractObjectTypeFactoryBean.class); + definition.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, + ResolvableType.forClassWithGenerics(MyBean.class, String.class))); + registry.registerBeanDefinition("myBean", definition); + } } abstract static class AbstractMyBean { } - static class MyBean extends AbstractMyBean { + static class MyBean extends AbstractMyBean { } static class TestFactoryBean implements FactoryBean { @@ -220,31 +243,26 @@ class ConfigurationWithFactoryBeanBeanEarlyDeductionTests { public Class getObjectType() { return this.instance.getClass(); } - } - static class MyFactoryBean extends TestFactoryBean { + static class MyFactoryBean extends TestFactoryBean> { public MyFactoryBean() { - super(new MyBean()); + super(new MyBean<>()); } - } static class RawWithAbstractObjectTypeFactoryBean implements FactoryBean { - private final Object object = new MyBean(); - @Override - public Object getObject() { - return object; + public Object getObject() throws Exception { + throw new IllegalStateException(); } @Override public Class getObjectType() { return MyBean.class; } - } }