Programmatic ObjectProvider retrieval through BeanFactory API
Introduces getBeanProvider(Class) and getBeanProvider(ResolvableType), also narrowing getBean(String, Class) and isTypeMatch(String, Class) to a non-null Class argument and enriching NoUniqueBeanDefinitionException with a full ResolvableType. In addition, ObjectProvider supports iterable/stream access for collection-style resolution of multiple matching beans now, and collection injection falls back to an empty collection in a single-constructor case with non-null arguments. Issue: SPR-17075 Issue: SPR-11419 Issue: SPR-15338
This commit is contained in:
@@ -27,14 +27,17 @@ import java.security.PrivilegedAction;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Priority;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
@@ -95,6 +98,7 @@ import org.springframework.tests.sample.beans.NestedTestBean;
|
||||
import org.springframework.tests.sample.beans.SideEffectBean;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.tests.sample.beans.factory.DummyFactory;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
@@ -1559,10 +1563,42 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchBeanDefinitionException.class)
|
||||
@Test
|
||||
public void testGetBeanByTypeInstanceWithNoneFound() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.getBean(ConstructorDependency.class, 42);
|
||||
|
||||
try {
|
||||
lbf.getBean(ConstructorDependency.class);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
lbf.getBean(ConstructorDependency.class, 42);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
ObjectProvider<ConstructorDependency> provider = lbf.getBeanProvider(ConstructorDependency.class);
|
||||
try {
|
||||
provider.getObject();
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
provider.getObject(42);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
assertNull(provider.getIfAvailable());
|
||||
assertNull(provider.getIfUnique());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1571,9 +1607,27 @@ public class DefaultListableBeanFactoryTests {
|
||||
RootBeanDefinition bd1 = createConstructorDependencyBeanDefinition(99);
|
||||
parent.registerBeanDefinition("bd1", bd1);
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(parent);
|
||||
ConstructorDependency bean = lbf.getBean(ConstructorDependency.class, 42);
|
||||
|
||||
ConstructorDependency bean = lbf.getBean(ConstructorDependency.class);
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(99));
|
||||
bean = lbf.getBean(ConstructorDependency.class, 42);
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(42));
|
||||
|
||||
ObjectProvider<ConstructorDependency> provider = lbf.getBeanProvider(ConstructorDependency.class);
|
||||
bean = provider.getObject();
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(99));
|
||||
bean = provider.getObject(42);
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(42));
|
||||
bean = provider.getIfAvailable();
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(99));
|
||||
bean = provider.getIfUnique();
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(99));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1583,12 +1637,66 @@ public class DefaultListableBeanFactoryTests {
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(ConstructorDependency.class);
|
||||
bd2.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd2.getConstructorArgumentValues().addGenericArgumentValue("43");
|
||||
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
|
||||
thrown.expect(NoUniqueBeanDefinitionException.class);
|
||||
lbf.getBean(ConstructorDependency.class, 42);
|
||||
try {
|
||||
lbf.getBean(ConstructorDependency.class);
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
lbf.getBean(ConstructorDependency.class, 42);
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
ObjectProvider<ConstructorDependency> provider = lbf.getBeanProvider(ConstructorDependency.class);
|
||||
try {
|
||||
provider.getObject();
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
provider.getObject(42);
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
provider.getIfAvailable();
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
assertNull(provider.getIfUnique());
|
||||
|
||||
Set<Object> resolved = new HashSet<>();
|
||||
for (ConstructorDependency instance : provider) {
|
||||
resolved.add(instance);
|
||||
}
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(lbf.getBean("bd1")));
|
||||
assertTrue(resolved.contains(lbf.getBean("bd2")));
|
||||
|
||||
resolved = new HashSet<>();
|
||||
provider.forEach(resolved::add);
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(lbf.getBean("bd1")));
|
||||
assertTrue(resolved.contains(lbf.getBean("bd2")));
|
||||
|
||||
resolved = provider.stream().collect(Collectors.toSet());
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(lbf.getBean("bd1")));
|
||||
assertTrue(resolved.contains(lbf.getBean("bd2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1599,9 +1707,46 @@ public class DefaultListableBeanFactoryTests {
|
||||
bd2.setPrimary(true);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
ConstructorDependency bean = lbf.getBean(ConstructorDependency.class, 42);
|
||||
|
||||
ConstructorDependency bean = lbf.getBean(ConstructorDependency.class);
|
||||
assertThat(bean.beanName, equalTo("bd2"));
|
||||
assertThat(bean.spouseAge, equalTo(43));
|
||||
bean = lbf.getBean(ConstructorDependency.class, 42);
|
||||
assertThat(bean.beanName, equalTo("bd2"));
|
||||
assertThat(bean.spouseAge, equalTo(42));
|
||||
|
||||
ObjectProvider<ConstructorDependency> provider = lbf.getBeanProvider(ConstructorDependency.class);
|
||||
bean = provider.getObject();
|
||||
assertThat(bean.beanName, equalTo("bd2"));
|
||||
assertThat(bean.spouseAge, equalTo(43));
|
||||
bean = provider.getObject(42);
|
||||
assertThat(bean.beanName, equalTo("bd2"));
|
||||
assertThat(bean.spouseAge, equalTo(42));
|
||||
bean = provider.getIfAvailable();
|
||||
assertThat(bean.beanName, equalTo("bd2"));
|
||||
assertThat(bean.spouseAge, equalTo(43));
|
||||
bean = provider.getIfUnique();
|
||||
assertThat(bean.beanName, equalTo("bd2"));
|
||||
assertThat(bean.spouseAge, equalTo(43));
|
||||
|
||||
Set<Object> resolved = new HashSet<>();
|
||||
for (ConstructorDependency instance : provider) {
|
||||
resolved.add(instance);
|
||||
}
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(lbf.getBean("bd1")));
|
||||
assertTrue(resolved.contains(lbf.getBean("bd2")));
|
||||
|
||||
resolved = new HashSet<>();
|
||||
provider.forEach(resolved::add);
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(lbf.getBean("bd1")));
|
||||
assertTrue(resolved.contains(lbf.getBean("bd2")));
|
||||
|
||||
resolved = provider.stream().collect(Collectors.toSet());
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(lbf.getBean("bd1")));
|
||||
assertTrue(resolved.contains(lbf.getBean("bd2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1611,9 +1756,9 @@ public class DefaultListableBeanFactoryTests {
|
||||
RootBeanDefinition bd2 = createConstructorDependencyBeanDefinition(43);
|
||||
bd1.setPrimary(true);
|
||||
bd2.setPrimary(true);
|
||||
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
|
||||
thrown.expect(NoUniqueBeanDefinitionException.class);
|
||||
thrown.expectMessage(containsString("more than one 'primary'"));
|
||||
lbf.getBean(ConstructorDependency.class, 42);
|
||||
@@ -1642,6 +1787,31 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanProviderSerialization() throws Exception {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.setSerializationId("test");
|
||||
|
||||
ObjectProvider<ConstructorDependency> provider = lbf.getBeanProvider(ConstructorDependency.class);
|
||||
ObjectProvider deserialized = (ObjectProvider) SerializationTestUtils.serializeAndDeserialize(provider);
|
||||
try {
|
||||
deserialized.getObject();
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
deserialized.getObject(42);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
assertNull(deserialized.getIfAvailable());
|
||||
assertNull(deserialized.getIfUnique());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanWithArgsNotCreatedForFactoryBeanChecking() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
@@ -2859,6 +3029,21 @@ public class DefaultListableBeanFactoryTests {
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ConstructorDependency that = (ConstructorDependency) o;
|
||||
return spouseAge == that.spouseAge &&
|
||||
Objects.equals(spouse, that.spouse) &&
|
||||
Objects.equals(beanName, that.beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(spouse, spouseAge, beanName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
@@ -811,13 +812,13 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleConstructorInjectionWithMultipleCandidatesAsOrderedCollection() {
|
||||
public void testSingleConstructorInjectionWithMultipleCandidatesAsRequiredCollection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorCollectionInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorRequiredCollectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
FixedOrder2NestedTestBean ntb1 = new FixedOrder2NestedTestBean();
|
||||
@@ -825,7 +826,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
FixedOrder1NestedTestBean ntb2 = new FixedOrder1NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean2", ntb2);
|
||||
|
||||
SingleConstructorCollectionInjectionBean bean = (SingleConstructorCollectionInjectionBean) bf.getBean("annotatedBean");
|
||||
SingleConstructorRequiredCollectionBean bean = (SingleConstructorRequiredCollectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertEquals(2, bean.getNestedTestBeans().size());
|
||||
assertSame(ntb2, bean.getNestedTestBeans().get(0));
|
||||
@@ -840,11 +841,52 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorCollectionInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorRequiredCollectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
|
||||
SingleConstructorCollectionInjectionBean bean = (SingleConstructorCollectionInjectionBean) bf.getBean("annotatedBean");
|
||||
SingleConstructorRequiredCollectionBean bean = (SingleConstructorRequiredCollectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertNotNull(bean.getNestedTestBeans());
|
||||
assertTrue(bean.getNestedTestBeans().isEmpty());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleConstructorInjectionWithMultipleCandidatesAsOrderedCollection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
FixedOrder2NestedTestBean ntb1 = new FixedOrder2NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean1", ntb1);
|
||||
FixedOrder1NestedTestBean ntb2 = new FixedOrder1NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean2", ntb2);
|
||||
|
||||
SingleConstructorOptionalCollectionBean bean = (SingleConstructorOptionalCollectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertEquals(2, bean.getNestedTestBeans().size());
|
||||
assertSame(ntb2, bean.getNestedTestBeans().get(0));
|
||||
assertSame(ntb1, bean.getNestedTestBeans().get(1));
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleConstructorInjectionWithEmptyCollectionAsNull() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
|
||||
SingleConstructorOptionalCollectionBean bean = (SingleConstructorOptionalCollectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertNull(bean.getNestedTestBeans());
|
||||
bf.destroySingletons();
|
||||
@@ -857,7 +899,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorCollectionInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
|
||||
|
||||
bf.getBean("annotatedBean");
|
||||
}
|
||||
@@ -869,7 +911,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorCollectionInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
|
||||
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
|
||||
tb.setFactoryMethodName("createTestBean");
|
||||
bf.registerBeanDefinition("testBean", tb);
|
||||
@@ -1333,17 +1375,17 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmartObjectFactoryInjectionWithPrototype() {
|
||||
public void testObjectProviderInjectionWithPrototype() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SmartObjectFactoryInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectProviderInjectionBean.class));
|
||||
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
|
||||
tbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("testBean", tbd);
|
||||
|
||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
ObjectProviderInjectionBean bean = (ObjectProviderInjectionBean) bf.getBean("annotatedBean");
|
||||
assertEquals(bf.getBean("testBean"), bean.getTestBean());
|
||||
assertEquals(bf.getBean("testBean", "myName"), bean.getTestBean("myName"));
|
||||
assertEquals(bf.getBean("testBean"), bean.getOptionalTestBean());
|
||||
@@ -1352,19 +1394,30 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertEquals(bf.getBean("testBean"), bean.getUniqueTestBean());
|
||||
assertEquals(bf.getBean("testBean"), bean.getUniqueTestBeanWithDefault());
|
||||
assertEquals(bf.getBean("testBean"), bean.consumeUniqueTestBean());
|
||||
|
||||
List<?> testBeans = bean.iterateTestBeans();
|
||||
assertEquals(1, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean")));
|
||||
testBeans = bean.forEachTestBeans();
|
||||
assertEquals(1, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean")));
|
||||
testBeans = bean.streamTestBeans();
|
||||
assertEquals(1, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean")));
|
||||
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmartObjectFactoryInjectionWithSingletonTarget() {
|
||||
public void testObjectProviderInjectionWithSingletonTarget() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SmartObjectFactoryInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectProviderInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
ObjectProviderInjectionBean bean = (ObjectProviderInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
assertSame(bf.getBean("testBean"), bean.getOptionalTestBean());
|
||||
assertSame(bf.getBean("testBean"), bean.getOptionalTestBeanWithDefault());
|
||||
@@ -1372,18 +1425,29 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertSame(bf.getBean("testBean"), bean.getUniqueTestBean());
|
||||
assertSame(bf.getBean("testBean"), bean.getUniqueTestBeanWithDefault());
|
||||
assertEquals(bf.getBean("testBean"), bean.consumeUniqueTestBean());
|
||||
|
||||
List<?> testBeans = bean.iterateTestBeans();
|
||||
assertEquals(1, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean")));
|
||||
testBeans = bean.forEachTestBeans();
|
||||
assertEquals(1, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean")));
|
||||
testBeans = bean.streamTestBeans();
|
||||
assertEquals(1, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean")));
|
||||
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmartObjectFactoryInjectionWithTargetNotAvailable() {
|
||||
public void testObjectProviderInjectionWithTargetNotAvailable() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SmartObjectFactoryInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectProviderInjectionBean.class));
|
||||
|
||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
ObjectProviderInjectionBean bean = (ObjectProviderInjectionBean) bf.getBean("annotatedBean");
|
||||
try {
|
||||
bean.getTestBean();
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
@@ -1397,20 +1461,28 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertEquals(new TestBean("default"), bean.getUniqueTestBeanWithDefault());
|
||||
assertNull(bean.getUniqueTestBean());
|
||||
assertNull(bean.consumeUniqueTestBean());
|
||||
|
||||
List<?> testBeans = bean.iterateTestBeans();
|
||||
assertTrue(testBeans.isEmpty());
|
||||
testBeans = bean.forEachTestBeans();
|
||||
assertTrue(testBeans.isEmpty());
|
||||
testBeans = bean.streamTestBeans();
|
||||
assertTrue(testBeans.isEmpty());
|
||||
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmartObjectFactoryInjectionWithTargetNotUnique() {
|
||||
public void testObjectProviderInjectionWithTargetNotUnique() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SmartObjectFactoryInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectProviderInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean1", new RootBeanDefinition(TestBean.class));
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
ObjectProviderInjectionBean bean = (ObjectProviderInjectionBean) bf.getBean("annotatedBean");
|
||||
try {
|
||||
bean.getTestBean();
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
@@ -1434,16 +1506,30 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
assertNull(bean.getUniqueTestBean());
|
||||
assertNull(bean.consumeUniqueTestBean());
|
||||
|
||||
List<?> testBeans = bean.iterateTestBeans();
|
||||
assertEquals(2, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean1")));
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean2")));
|
||||
testBeans = bean.forEachTestBeans();
|
||||
assertEquals(2, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean1")));
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean2")));
|
||||
testBeans = bean.streamTestBeans();
|
||||
assertEquals(2, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean1")));
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean2")));
|
||||
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmartObjectFactoryInjectionWithTargetPrimary() {
|
||||
public void testObjectProviderInjectionWithTargetPrimary() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SmartObjectFactoryInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectProviderInjectionBean.class));
|
||||
RootBeanDefinition tb1 = new RootBeanDefinition(TestBean.class);
|
||||
tb1.setPrimary(true);
|
||||
bf.registerBeanDefinition("testBean1", tb1);
|
||||
@@ -1451,13 +1537,27 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
tb2.setLazyInit(true);
|
||||
bf.registerBeanDefinition("testBean2", tb2);
|
||||
|
||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
ObjectProviderInjectionBean bean = (ObjectProviderInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean1"), bean.getTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.getOptionalTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.consumeOptionalTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.getUniqueTestBean());
|
||||
assertSame(bf.getBean("testBean1"), bean.consumeUniqueTestBean());
|
||||
assertFalse(bf.containsSingleton("testBean2"));
|
||||
|
||||
List<?> testBeans = bean.iterateTestBeans();
|
||||
assertEquals(2, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean1")));
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean2")));
|
||||
testBeans = bean.forEachTestBeans();
|
||||
assertEquals(2, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean1")));
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean2")));
|
||||
testBeans = bean.streamTestBeans();
|
||||
assertEquals(2, testBeans.size());
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean1")));
|
||||
assertTrue(testBeans.contains(bf.getBean("testBean2")));
|
||||
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@@ -2941,13 +3041,34 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
public static class SingleConstructorCollectionInjectionBean {
|
||||
public static class SingleConstructorRequiredCollectionBean {
|
||||
|
||||
private ITestBean testBean;
|
||||
|
||||
private List<NestedTestBean> nestedTestBeans;
|
||||
|
||||
public SingleConstructorCollectionInjectionBean(ITestBean testBean,
|
||||
public SingleConstructorRequiredCollectionBean(ITestBean testBean, List<NestedTestBean> nestedTestBeans) {
|
||||
this.testBean = testBean;
|
||||
this.nestedTestBeans = nestedTestBeans;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean() {
|
||||
return this.testBean;
|
||||
}
|
||||
|
||||
public List<NestedTestBean> getNestedTestBeans() {
|
||||
return this.nestedTestBeans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SingleConstructorOptionalCollectionBean {
|
||||
|
||||
private ITestBean testBean;
|
||||
|
||||
private List<NestedTestBean> nestedTestBeans;
|
||||
|
||||
public SingleConstructorOptionalCollectionBean(ITestBean testBean,
|
||||
@Autowired(required = false) List<NestedTestBean> nestedTestBeans) {
|
||||
this.testBean = testBean;
|
||||
this.nestedTestBeans = nestedTestBeans;
|
||||
@@ -3096,46 +3217,64 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
public static class SmartObjectFactoryInjectionBean {
|
||||
public static class ObjectProviderInjectionBean {
|
||||
|
||||
@Autowired
|
||||
private ObjectProvider<TestBean> testBeanFactory;
|
||||
private ObjectProvider<TestBean> testBeanProvider;
|
||||
|
||||
private TestBean consumedTestBean;
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBeanFactory.getObject();
|
||||
return this.testBeanProvider.getObject();
|
||||
}
|
||||
|
||||
public TestBean getTestBean(String name) {
|
||||
return this.testBeanFactory.getObject(name);
|
||||
return this.testBeanProvider.getObject(name);
|
||||
}
|
||||
|
||||
public TestBean getOptionalTestBean() {
|
||||
return this.testBeanFactory.getIfAvailable();
|
||||
return this.testBeanProvider.getIfAvailable();
|
||||
}
|
||||
|
||||
public TestBean getOptionalTestBeanWithDefault() {
|
||||
return this.testBeanFactory.getIfAvailable(() -> new TestBean("default"));
|
||||
return this.testBeanProvider.getIfAvailable(() -> new TestBean("default"));
|
||||
}
|
||||
|
||||
public TestBean consumeOptionalTestBean() {
|
||||
this.testBeanFactory.ifAvailable(tb -> consumedTestBean = tb);
|
||||
this.testBeanProvider.ifAvailable(tb -> consumedTestBean = tb);
|
||||
return consumedTestBean;
|
||||
}
|
||||
|
||||
public TestBean getUniqueTestBean() {
|
||||
return this.testBeanFactory.getIfUnique();
|
||||
return this.testBeanProvider.getIfUnique();
|
||||
}
|
||||
|
||||
public TestBean getUniqueTestBeanWithDefault() {
|
||||
return this.testBeanFactory.getIfUnique(() -> new TestBean("default"));
|
||||
return this.testBeanProvider.getIfUnique(() -> new TestBean("default"));
|
||||
}
|
||||
|
||||
public TestBean consumeUniqueTestBean() {
|
||||
this.testBeanFactory.ifUnique(tb -> consumedTestBean = tb);
|
||||
this.testBeanProvider.ifUnique(tb -> consumedTestBean = tb);
|
||||
return consumedTestBean;
|
||||
}
|
||||
|
||||
public List<TestBean> iterateTestBeans() {
|
||||
List<TestBean> resolved = new LinkedList<>();
|
||||
for (TestBean tb : this.testBeanProvider) {
|
||||
resolved.add(tb);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
public List<TestBean> forEachTestBeans() {
|
||||
List<TestBean> resolved = new LinkedList<>();
|
||||
this.testBeanProvider.forEach(resolved::add);
|
||||
return resolved;
|
||||
}
|
||||
|
||||
public List<TestBean> streamTestBeans() {
|
||||
return this.testBeanProvider.stream().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
@@ -37,6 +38,8 @@ import org.mockito.Mockito;
|
||||
import org.springframework.beans.PropertyEditorRegistrar;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.beans.propertyeditors.CustomNumberEditor;
|
||||
@@ -160,7 +163,7 @@ public class BeanFactoryGenericsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericListOfArraysProperty() throws MalformedURLException {
|
||||
public void testGenericListOfArraysProperty() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
new ClassPathResource("genericBeanTests.xml", getClass()));
|
||||
@@ -863,6 +866,66 @@ public class BeanFactoryGenericsTests {
|
||||
assertEquals("store1", doubleStoreNames[0]);
|
||||
assertEquals(1, floatStoreNames.length);
|
||||
assertEquals("store2", floatStoreNames[0]);
|
||||
|
||||
ObjectProvider<NumberStore<?>> numberStoreProvider = bf.getBeanProvider(ResolvableType.forClass(NumberStore.class));
|
||||
ObjectProvider<NumberStore<Double>> doubleStoreProvider = bf.getBeanProvider(ResolvableType.forClassWithGenerics(NumberStore.class, Double.class));
|
||||
ObjectProvider<NumberStore<Float>> floatStoreProvider = bf.getBeanProvider(ResolvableType.forClassWithGenerics(NumberStore.class, Float.class));
|
||||
try {
|
||||
numberStoreProvider.getObject();
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
numberStoreProvider.getIfAvailable();
|
||||
fail("Should have thrown NoUniqueBeanDefinitionException");
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
assertNull(numberStoreProvider.getIfUnique());
|
||||
assertSame(bf.getBean("store1"), doubleStoreProvider.getObject());
|
||||
assertSame(bf.getBean("store1"), doubleStoreProvider.getIfAvailable());
|
||||
assertSame(bf.getBean("store1"), doubleStoreProvider.getIfUnique());
|
||||
assertSame(bf.getBean("store2"), floatStoreProvider.getObject());
|
||||
assertSame(bf.getBean("store2"), floatStoreProvider.getIfAvailable());
|
||||
assertSame(bf.getBean("store2"), floatStoreProvider.getIfUnique());
|
||||
|
||||
Set<Object> resolved = new HashSet<>();
|
||||
for (NumberStore<?> instance : numberStoreProvider) {
|
||||
resolved.add(instance);
|
||||
}
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(bf.getBean("store1")));
|
||||
assertTrue(resolved.contains(bf.getBean("store2")));
|
||||
|
||||
resolved = numberStoreProvider.stream().collect(Collectors.toSet());
|
||||
assertEquals(2, resolved.size());
|
||||
assertTrue(resolved.contains(bf.getBean("store1")));
|
||||
assertTrue(resolved.contains(bf.getBean("store2")));
|
||||
|
||||
resolved = new HashSet<>();
|
||||
for (NumberStore<Double> instance : doubleStoreProvider) {
|
||||
resolved.add(instance);
|
||||
}
|
||||
assertEquals(1, resolved.size());
|
||||
assertTrue(resolved.contains(bf.getBean("store1")));
|
||||
|
||||
resolved = doubleStoreProvider.stream().collect(Collectors.toSet());
|
||||
assertEquals(1, resolved.size());
|
||||
assertTrue(resolved.contains(bf.getBean("store1")));
|
||||
|
||||
resolved = new HashSet<>();
|
||||
for (NumberStore<Float> instance : floatStoreProvider) {
|
||||
resolved.add(instance);
|
||||
}
|
||||
assertEquals(1, resolved.size());
|
||||
assertTrue(resolved.contains(bf.getBean("store2")));
|
||||
|
||||
resolved = floatStoreProvider.stream().collect(Collectors.toSet());
|
||||
assertEquals(1, resolved.size());
|
||||
assertTrue(resolved.contains(bf.getBean("store2")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user