Consistent ordered list access and lazy streaming for ObjectProvider

Includes fallback match for collection/map dependency if qualified.

Issue: SPR-17272
Issue: SPR-17197
This commit is contained in:
Juergen Hoeller
2018-09-13 18:23:19 +02:00
parent 068565172e
commit 65c8fa400f
12 changed files with 304 additions and 137 deletions

View File

@@ -71,6 +71,7 @@ import org.springframework.tests.sample.beans.NestedTestBean;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.SerializationTestUtils;
import org.springframework.util.comparator.Comparators;
import static org.junit.Assert.*;
@@ -978,6 +979,19 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(bf.getBean("myTestBeanMap"), bean.getTestBeanMap());
}
@Test
public void testConstructorInjectionWithPlainHashMapAsBean() {
RootBeanDefinition bd = new RootBeanDefinition(QualifiedMapConstructorInjectionBean.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
bf.registerBeanDefinition("annotatedBean", bd);
bf.registerBeanDefinition("myTestBeanMap", new RootBeanDefinition(HashMap.class));
QualifiedMapConstructorInjectionBean bean = (QualifiedMapConstructorInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("myTestBeanMap"), bean.getTestBeanMap());
bean = (QualifiedMapConstructorInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("myTestBeanMap"), bean.getTestBeanMap());
}
@Test
public void testConstructorInjectionWithTypedSetAsBean() {
RootBeanDefinition bd = new RootBeanDefinition(SetConstructorInjectionBean.class);
@@ -1162,6 +1176,9 @@ public class AutowiredAnnotationBeanPostProcessorTests {
testBeans = bean.streamTestBeans();
assertEquals(1, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean")));
testBeans = bean.sortedTestBeans();
assertEquals(1, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean")));
}
@Test
@@ -1187,6 +1204,9 @@ public class AutowiredAnnotationBeanPostProcessorTests {
testBeans = bean.streamTestBeans();
assertEquals(1, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean")));
testBeans = bean.sortedTestBeans();
assertEquals(1, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean")));
}
@Test
@@ -1214,6 +1234,8 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertTrue(testBeans.isEmpty());
testBeans = bean.streamTestBeans();
assertTrue(testBeans.isEmpty());
testBeans = bean.sortedTestBeans();
assertTrue(testBeans.isEmpty());
}
@Test
@@ -1249,25 +1271,33 @@ public class AutowiredAnnotationBeanPostProcessorTests {
List<?> testBeans = bean.iterateTestBeans();
assertEquals(2, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean1")));
assertTrue(testBeans.contains(bf.getBean("testBean2")));
assertSame(bf.getBean("testBean1"), testBeans.get(0));
assertSame(bf.getBean("testBean2"), testBeans.get(1));
testBeans = bean.forEachTestBeans();
assertEquals(2, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean1")));
assertTrue(testBeans.contains(bf.getBean("testBean2")));
assertSame(bf.getBean("testBean1"), testBeans.get(0));
assertSame(bf.getBean("testBean2"), testBeans.get(1));
testBeans = bean.streamTestBeans();
assertEquals(2, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean1")));
assertTrue(testBeans.contains(bf.getBean("testBean2")));
assertSame(bf.getBean("testBean1"), testBeans.get(0));
assertSame(bf.getBean("testBean2"), testBeans.get(1));
testBeans = bean.sortedTestBeans();
assertEquals(2, testBeans.size());
assertSame(bf.getBean("testBean1"), testBeans.get(0));
assertSame(bf.getBean("testBean2"), testBeans.get(1));
}
@Test
public void testObjectProviderInjectionWithTargetPrimary() {
bf.setDependencyComparator(Comparators.comparable());
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectProviderInjectionBean.class));
RootBeanDefinition tb1 = new RootBeanDefinition(TestBean.class);
tb1.getPropertyValues().add("name", "yours");
tb1.setPrimary(true);
bf.registerBeanDefinition("testBean1", tb1);
RootBeanDefinition tb2 = new RootBeanDefinition(TestBean.class);
tb2.getPropertyValues().add("name", "mine");
tb2.setLazyInit(true);
bf.registerBeanDefinition("testBean2", tb2);
@@ -1281,16 +1311,20 @@ public class AutowiredAnnotationBeanPostProcessorTests {
List<?> testBeans = bean.iterateTestBeans();
assertEquals(2, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean1")));
assertTrue(testBeans.contains(bf.getBean("testBean2")));
assertSame(bf.getBean("testBean1"), testBeans.get(0));
assertSame(bf.getBean("testBean2"), testBeans.get(1));
testBeans = bean.forEachTestBeans();
assertEquals(2, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean1")));
assertTrue(testBeans.contains(bf.getBean("testBean2")));
assertSame(bf.getBean("testBean1"), testBeans.get(0));
assertSame(bf.getBean("testBean2"), testBeans.get(1));
testBeans = bean.streamTestBeans();
assertEquals(2, testBeans.size());
assertTrue(testBeans.contains(bf.getBean("testBean1")));
assertTrue(testBeans.contains(bf.getBean("testBean2")));
assertSame(bf.getBean("testBean1"), testBeans.get(0));
assertSame(bf.getBean("testBean2"), testBeans.get(1));
testBeans = bean.sortedTestBeans();
assertEquals(2, testBeans.size());
assertSame(bf.getBean("testBean1"), testBeans.get(1));
assertSame(bf.getBean("testBean2"), testBeans.get(0));
}
@Test
@@ -2668,6 +2702,21 @@ public class AutowiredAnnotationBeanPostProcessorTests {
}
public static class QualifiedMapConstructorInjectionBean {
private Map<String, TestBean> testBeanMap;
@Autowired
public QualifiedMapConstructorInjectionBean(@Qualifier("myTestBeanMap") Map<String, TestBean> testBeanMap) {
this.testBeanMap = testBeanMap;
}
public Map<String, TestBean> getTestBeanMap() {
return this.testBeanMap;
}
}
public static class SetConstructorInjectionBean {
private Set<TestBean> testBeanSet;
@@ -2834,6 +2883,10 @@ public class AutowiredAnnotationBeanPostProcessorTests {
public List<TestBean> streamTestBeans() {
return this.testBeanProvider.stream().collect(Collectors.toList());
}
public List<TestBean> sortedTestBeans() {
return this.testBeanProvider.toList();
}
}

View File

@@ -53,6 +53,7 @@ import org.springframework.tests.sample.beans.GenericBean;
import org.springframework.tests.sample.beans.GenericIntegerBean;
import org.springframework.tests.sample.beans.GenericSetOfIntegerBean;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.comparator.Comparators;
import static org.junit.Assert.*;
@@ -134,7 +135,7 @@ public class BeanFactoryGenericsTests {
}
@Test
public void testGenericListPropertyWithOptionalAutowiring() throws MalformedURLException {
public void testGenericListPropertyWithOptionalAutowiring() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class);
@@ -846,6 +847,7 @@ public class BeanFactoryGenericsTests {
public void testGenericMatchingWithFullTypeDifferentiation() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
bf.setDependencyComparator(Comparators.comparable());
bf.registerBeanDefinition("store1", new RootBeanDefinition(DoubleStore.class));
bf.registerBeanDefinition("store2", new RootBeanDefinition(FloatStore.class));
@@ -892,38 +894,51 @@ public class BeanFactoryGenericsTests {
assertSame(bf.getBean("store2"), floatStoreProvider.getIfAvailable());
assertSame(bf.getBean("store2"), floatStoreProvider.getIfUnique());
Set<Object> resolved = new HashSet<>();
List<NumberStore<?>> resolved = new ArrayList<>();
for (NumberStore<?> instance : numberStoreProvider) {
resolved.add(instance);
}
assertEquals(2, resolved.size());
assertTrue(resolved.contains(bf.getBean("store1")));
assertTrue(resolved.contains(bf.getBean("store2")));
assertSame(bf.getBean("store1"), resolved.get(0));
assertSame(bf.getBean("store2"), resolved.get(1));
resolved = numberStoreProvider.stream().collect(Collectors.toSet());
resolved = numberStoreProvider.stream().collect(Collectors.toList());
assertEquals(2, resolved.size());
assertTrue(resolved.contains(bf.getBean("store1")));
assertTrue(resolved.contains(bf.getBean("store2")));
assertSame(bf.getBean("store1"), resolved.get(0));
assertSame(bf.getBean("store2"), resolved.get(1));
resolved = new HashSet<>();
resolved = numberStoreProvider.toList();
assertEquals(2, resolved.size());
assertSame(bf.getBean("store2"), resolved.get(0));
assertSame(bf.getBean("store1"), resolved.get(1));
resolved = new ArrayList<>();
for (NumberStore<Double> instance : doubleStoreProvider) {
resolved.add(instance);
}
assertEquals(1, resolved.size());
assertTrue(resolved.contains(bf.getBean("store1")));
resolved = doubleStoreProvider.stream().collect(Collectors.toSet());
resolved = doubleStoreProvider.stream().collect(Collectors.toList());
assertEquals(1, resolved.size());
assertTrue(resolved.contains(bf.getBean("store1")));
resolved = new HashSet<>();
resolved = (List) doubleStoreProvider.toList();
assertEquals(1, resolved.size());
assertTrue(resolved.contains(bf.getBean("store1")));
resolved = new ArrayList<>();
for (NumberStore<Float> instance : floatStoreProvider) {
resolved.add(instance);
}
assertEquals(1, resolved.size());
assertTrue(resolved.contains(bf.getBean("store2")));
resolved = floatStoreProvider.stream().collect(Collectors.toSet());
resolved = floatStoreProvider.stream().collect(Collectors.toList());
assertEquals(1, resolved.size());
assertTrue(resolved.contains(bf.getBean("store2")));
resolved = (List) floatStoreProvider.toList();
assertEquals(1, resolved.size());
assertTrue(resolved.contains(bf.getBean("store2")));
}
@@ -991,7 +1006,12 @@ public class BeanFactoryGenericsTests {
}
public static class NumberStore<T extends Number> {
public static class NumberStore<T extends Number> implements Comparable<NumberStore> {
@Override
public int compareTo(NumberStore other) {
return getClass().getName().compareTo(other.getClass().getName()) * -1;
}
}