Revised tests for generic FactoryBean type matching (backported)
See gh-32489
This commit is contained in:
@@ -29,6 +29,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
@@ -756,25 +758,31 @@ class BeanFactoryGenericsTests {
|
||||
assertThat(floatStoreNames).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericMatchingWithFullTypeDifferentiation() {
|
||||
@ParameterizedTest
|
||||
@ValueSource(classes = {NumberStoreFactory.class, NumberStoreFactoryBeans.class})
|
||||
void genericMatchingWithFullTypeDifferentiation(Class<?> factoryClass) {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
|
||||
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
|
||||
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(NumberStoreFactory.class);
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(factoryClass);
|
||||
bd1.setFactoryMethodName("newDoubleStore");
|
||||
bf.registerBeanDefinition("store1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(NumberStoreFactory.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(factoryClass);
|
||||
bd2.setFactoryMethodName("newFloatStore");
|
||||
bf.registerBeanDefinition("store2", bd2);
|
||||
bf.registerBeanDefinition("numberBean",
|
||||
new RootBeanDefinition(NumberBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
RootBeanDefinition bd3 = new RootBeanDefinition(NumberBean.class);
|
||||
bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd3.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
bf.registerBeanDefinition("numberBean", bd3);
|
||||
|
||||
NumberBean nb = bf.getBean(NumberBean.class);
|
||||
NumberStore<?> store1 = bf.getBean("store1", NumberStore.class);
|
||||
assertThat(nb.getDoubleStore()).isSameAs(store1);
|
||||
NumberStore<?> store2 = bf.getBean("store2", NumberStore.class);
|
||||
NumberBean nb = bf.getBean(NumberBean.class);
|
||||
assertThat(nb.getDoubleStore()).isSameAs(store1);
|
||||
assertThat(nb.getFloatStore()).isSameAs(store2);
|
||||
nb = bf.getBean(NumberBean.class);
|
||||
assertThat(nb.getDoubleStore()).isSameAs(store1);
|
||||
assertThat(nb.getFloatStore()).isSameAs(store2);
|
||||
|
||||
String[] numberStoreNames = bf.getBeanNamesForType(ResolvableType.forClass(NumberStore.class));
|
||||
@@ -822,16 +830,17 @@ class BeanFactoryGenericsTests {
|
||||
assertThat(floatStoreProvider.orderedStream()).singleElement().isEqualTo(store2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericMatchingWithUnresolvedOrderedStream() {
|
||||
@ParameterizedTest
|
||||
@ValueSource(classes = {NumberStoreFactory.class, NumberStoreFactoryBeans.class})
|
||||
void genericMatchingWithUnresolvedOrderedStream(Class<?> factoryClass) {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
|
||||
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
|
||||
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(NumberStoreFactory.class);
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(factoryClass);
|
||||
bd1.setFactoryMethodName("newDoubleStore");
|
||||
bf.registerBeanDefinition("store1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(NumberStoreFactory.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(factoryClass);
|
||||
bd2.setFactoryMethodName("newFloatStore");
|
||||
bf.registerBeanDefinition("store2", bd2);
|
||||
|
||||
@@ -854,7 +863,22 @@ class BeanFactoryGenericsTests {
|
||||
bf.registerBeanDefinition("myFactoryBeanHolder",
|
||||
new RootBeanDefinition(MyFactoryBeanHolder.class, AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
|
||||
assertThat(bf.getBean(MyFactoryBeanHolder.class).factoryBeans).contains(bf.getBean(MyFactoryBean.class));
|
||||
assertThat(bf.getBean(MyFactoryBeanHolder.class).factoryBeans).containsOnly(bf.getBean(MyFactoryBean.class));
|
||||
}
|
||||
|
||||
@Test // gh-32489
|
||||
void genericMatchingAgainstLazyFactoryBeanClass() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
|
||||
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MyFactoryBean.class);
|
||||
bd.setTargetType(ResolvableType.forClassWithGenerics(MyFactoryBean.class, String.class));
|
||||
bd.setLazyInit(true);
|
||||
bf.registerBeanDefinition("myFactoryBean", bd);
|
||||
bf.registerBeanDefinition("myFactoryBeanHolder",
|
||||
new RootBeanDefinition(MyFactoryBeanHolder.class, AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
|
||||
assertThat(bf.getBean(MyFactoryBeanHolder.class).factoryBeans).containsOnly(bf.getBean(MyFactoryBean.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -974,6 +998,38 @@ class BeanFactoryGenericsTests {
|
||||
}
|
||||
|
||||
|
||||
public static class NumberStoreFactoryBeans {
|
||||
|
||||
@Order(1)
|
||||
public static FactoryBean<NumberStore<Double>> newDoubleStore() {
|
||||
return new FactoryBean<>() {
|
||||
@Override
|
||||
public NumberStore<Double> getObject() {
|
||||
return new DoubleStore();
|
||||
}
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return DoubleStore.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Order(0)
|
||||
public static FactoryBean<NumberStore<Float>> newFloatStore() {
|
||||
return new FactoryBean<>() {
|
||||
@Override
|
||||
public NumberStore<Float> getObject() {
|
||||
return new FloatStore();
|
||||
}
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return FloatStore.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface MyGenericInterfaceForFactoryBeans<T> {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -307,8 +307,8 @@ class AnnotationConfigApplicationContextTests {
|
||||
assertThat(ObjectUtils.containsElement(context.getBeanNamesForType(BeanC.class), "c")).isTrue();
|
||||
|
||||
assertThat(context.getBeansOfType(BeanA.class)).isEmpty();
|
||||
assertThat(context.getBeansOfType(BeanB.class).values().iterator().next()).isSameAs(context.getBean(BeanB.class));
|
||||
assertThat(context.getBeansOfType(BeanC.class).values().iterator().next()).isSameAs(context.getBean(BeanC.class));
|
||||
assertThat(context.getBeansOfType(BeanB.class).values()).singleElement().isSameAs(context.getBean(BeanB.class));
|
||||
assertThat(context.getBeansOfType(BeanC.class).values()).singleElement().isSameAs(context.getBean(BeanC.class));
|
||||
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
|
||||
.isThrownBy(() -> context.getBeanFactory().resolveNamedBean(BeanA.class));
|
||||
@@ -409,15 +409,17 @@ class AnnotationConfigApplicationContextTests {
|
||||
bd2.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class)));
|
||||
bd2.setLazyInit(true);
|
||||
context.registerBeanDefinition("fb2", bd2);
|
||||
context.registerBeanDefinition("ip", new RootBeanDefinition(FactoryBeanInjectionPoints.class));
|
||||
RootBeanDefinition bd3 = new RootBeanDefinition(FactoryBeanInjectionPoints.class);
|
||||
bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
context.registerBeanDefinition("ip", bd3);
|
||||
context.refresh();
|
||||
|
||||
assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryBean).isSameAs(context.getBean("&fb1"));
|
||||
assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class);
|
||||
assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class);
|
||||
assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2);
|
||||
assertThat(context.getBeanNamesForType(GenericHolderFactoryBean.class)).hasSize(1);
|
||||
assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryBean).isSameAs(context.getBean("&fb1"));
|
||||
assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -425,7 +427,7 @@ class AnnotationConfigApplicationContextTests {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition();
|
||||
bd1.setBeanClass(GenericHolderFactoryBean.class);
|
||||
bd1.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Object.class)));
|
||||
bd1.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, String.class)));
|
||||
bd1.setLazyInit(true);
|
||||
context.registerBeanDefinition("fb1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition();
|
||||
@@ -433,13 +435,17 @@ class AnnotationConfigApplicationContextTests {
|
||||
bd2.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class)));
|
||||
bd2.setLazyInit(true);
|
||||
context.registerBeanDefinition("fb2", bd2);
|
||||
context.registerBeanDefinition("ip", new RootBeanDefinition(FactoryResultInjectionPoint.class));
|
||||
RootBeanDefinition bd3 = new RootBeanDefinition(FactoryBeanInjectionPoints.class);
|
||||
bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
context.registerBeanDefinition("ip", bd3);
|
||||
context.refresh();
|
||||
|
||||
assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class);
|
||||
assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class);
|
||||
assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2);
|
||||
assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -453,14 +459,17 @@ class AnnotationConfigApplicationContextTests {
|
||||
bd2.setBeanClass(UntypedFactoryBean.class);
|
||||
bd2.setTargetType(ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class));
|
||||
context.registerBeanDefinition("fb2", bd2);
|
||||
context.registerBeanDefinition("ip", new RootBeanDefinition(FactoryResultInjectionPoint.class));
|
||||
RootBeanDefinition bd3 = new RootBeanDefinition(FactoryResultInjectionPoint.class);
|
||||
bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
context.registerBeanDefinition("ip", bd3);
|
||||
context.refresh();
|
||||
|
||||
assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class);
|
||||
assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class);
|
||||
assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2);
|
||||
assertThat(context.getBeanNamesForType(GenericHolderFactoryBean.class)).hasSize(1);
|
||||
assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user