Map resolution for multiple beans applies to plain Map interface declaration only

Issue: SPR-15117
This commit is contained in:
Juergen Hoeller 2017-01-12 21:15:41 +01:00
parent 9e6aa0ff59
commit 8084da59a7
2 changed files with 146 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -1173,7 +1173,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
return result;
}
else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
else if (Map.class == type) {
Class<?> keyType = descriptor.getMapKeyType();
if (String.class != keyType) {
return null;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -929,6 +929,28 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(bf.getBean("myTestBeanMap"), bean.getTestBeanMap());
}
@Test
public void testConstructorInjectionWithCustomMapAsBean() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
RootBeanDefinition bd = new RootBeanDefinition(CustomMapConstructorInjectionBean.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
bf.registerBeanDefinition("annotatedBean", bd);
RootBeanDefinition tbm = new RootBeanDefinition(CustomCollectionFactoryMethods.class);
tbm.setUniqueFactoryMethodName("testBeanMap");
bf.registerBeanDefinition("myTestBeanMap", tbm);
bf.registerSingleton("testBean1", new TestBean());
bf.registerSingleton("testBean2", new TestBean());
CustomMapConstructorInjectionBean bean = (CustomMapConstructorInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("myTestBeanMap"), bean.getTestBeanMap());
bean = (CustomMapConstructorInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("myTestBeanMap"), bean.getTestBeanMap());
}
@Test
public void testConstructorInjectionWithTypedSetAsBean() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@ -972,6 +994,26 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(bf.getBean("myTestBeanSet"), bean.getTestBeanSet());
}
@Test
public void testConstructorInjectionWithCustomSetAsBean() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
RootBeanDefinition bd = new RootBeanDefinition(CustomSetConstructorInjectionBean.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
bf.registerBeanDefinition("annotatedBean", bd);
RootBeanDefinition tbs = new RootBeanDefinition(CustomCollectionFactoryMethods.class);
tbs.setUniqueFactoryMethodName("testBeanSet");
bf.registerBeanDefinition("myTestBeanSet", tbs);
CustomSetConstructorInjectionBean bean = (CustomSetConstructorInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("myTestBeanSet"), bean.getTestBeanSet());
bean = (CustomSetConstructorInjectionBean) bf.getBean("annotatedBean");
assertSame(bf.getBean("myTestBeanSet"), bean.getTestBeanSet());
}
@Test
public void testSelfReference() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@ -2195,6 +2237,18 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertNotNull(bf.getBean("annotatedBean"));
}
@Test @Ignore // SPR-15125
public void testFactoryBeanSelfInjection() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SelfInjectingFactoryBean.class));
SelfInjectingFactoryBean bean = bf.getBean(SelfInjectingFactoryBean.class);
assertSame(bf.getBean("annotatedBean"), bean.testBean);
}
@Qualifier("integerRepo")
private Repository<?> integerRepositoryQualifierProvider;
@ -3251,7 +3305,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
public interface GenericInterface2<K> {
public String doSomethingMoreGeneric(K o);
String doSomethingMoreGeneric(K o);
}
@ -3437,6 +3491,70 @@ public class AutowiredAnnotationBeanPostProcessorTests {
}
public static class CustomCollectionFactoryMethods {
public static CustomMap<String, TestBean> testBeanMap() {
CustomMap<String, TestBean> tbm = new CustomHashMap<>();
tbm.put("testBean1", new TestBean("tb1"));
tbm.put("testBean2", new TestBean("tb2"));
return tbm;
}
public static CustomSet<TestBean> testBeanSet() {
CustomSet<TestBean> tbs = new CustomHashSet<>();
tbs.add(new TestBean("tb1"));
tbs.add(new TestBean("tb2"));
return tbs;
}
}
public static class CustomMapConstructorInjectionBean {
private CustomMap<String, TestBean> testBeanMap;
@Autowired
public CustomMapConstructorInjectionBean(CustomMap<String, TestBean> testBeanMap) {
this.testBeanMap = testBeanMap;
}
public CustomMap<String, TestBean> getTestBeanMap() {
return this.testBeanMap;
}
}
public static class CustomSetConstructorInjectionBean {
private CustomSet<TestBean> testBeanSet;
@Autowired
public CustomSetConstructorInjectionBean(CustomSet<TestBean> testBeanSet) {
this.testBeanSet = testBeanSet;
}
public CustomSet<TestBean> getTestBeanSet() {
return this.testBeanSet;
}
}
public interface CustomMap<K, V> extends Map<K, V> {
}
public static class CustomHashMap<K, V> extends LinkedHashMap<K, V> implements CustomMap<K, V> {
}
public interface CustomSet<E> extends Set<E> {
}
public static class CustomHashSet<E> extends LinkedHashSet<E> implements CustomSet<E> {
}
public static class AnnotatedDefaultConstructorBean {
@Autowired
@ -3444,4 +3562,28 @@ public class AutowiredAnnotationBeanPostProcessorTests {
}
}
public static class SelfInjectingFactoryBean implements FactoryBean<TestBean> {
private final TestBean exposedTestBean = new TestBean();
@Autowired
TestBean testBean;
@Override
public TestBean getObject() {
return exposedTestBean;
}
@Override
public Class<?> getObjectType() {
return TestBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
}