Fixed resolveReturnTypeForFactoryMethod to unwrap TypedStringValue

XML-defined arguments values are initially turned into TypedStringValue wrappers. If we encounter an unresolved argument, we need to unwrap such a TypedStringValue and then try to treat its content as a class name.

Issue: SPR-11034
This commit is contained in:
Juergen Hoeller
2013-10-27 21:26:04 +01:00
parent 671fad3cb5
commit 960ba379ca
3 changed files with 76 additions and 12 deletions

View File

@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
@@ -35,6 +36,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
@@ -1355,6 +1357,42 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertSame(repo, bean.stringRepositoryMap.get("repo"));
}
@Test
public void testGenericsBasedFieldInjectionWithSimpleMatchAndMockito() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
RootBeanDefinition bd = new RootBeanDefinition(RepositoryFieldInjectionBeanWithSimpleMatch.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
bf.registerBeanDefinition("annotatedBean", bd);
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setBeanClassName(Mockito.class.getName());
rbd.setFactoryMethodName("mock");
// TypedStringValue used to be equivalent to an XML-defined argument String
rbd.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue(Repository.class.getName()));
bf.registerBeanDefinition("repo", rbd);
RepositoryFieldInjectionBeanWithSimpleMatch bean = (RepositoryFieldInjectionBeanWithSimpleMatch) bf.getBean("annotatedBean");
Repository repo = bf.getBean("repo", Repository.class);
assertSame(repo, bean.repository);
assertSame(repo, bean.stringRepository);
assertSame(1, bean.repositoryArray.length);
assertSame(1, bean.stringRepositoryArray.length);
assertSame(repo, bean.repositoryArray[0]);
assertSame(repo, bean.stringRepositoryArray[0]);
assertSame(1, bean.repositoryList.size());
assertSame(1, bean.stringRepositoryList.size());
assertSame(repo, bean.repositoryList.get(0));
assertSame(repo, bean.stringRepositoryList.get(0));
assertSame(1, bean.repositoryMap.size());
assertSame(1, bean.stringRepositoryMap.size());
assertSame(repo, bean.repositoryMap.get("repo"));
assertSame(repo, bean.stringRepositoryMap.get("repo"));
}
@Test
public void testGenericsBasedMethodInjection() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();

View File

@@ -37,6 +37,7 @@ 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.config.TypedStringValue;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.core.io.ClassPathResource;
@@ -719,6 +720,21 @@ public class BeanFactoryGenericsTests {
assertEquals(1, beans.size());
}
@Test
public void parameterizedInstanceFactoryMethodWithWrappedClassName() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setBeanClassName(Mockito.class.getName());
rbd.setFactoryMethodName("mock");
// TypedStringValue used to be equivalent to an XML-defined argument String
rbd.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue(Runnable.class.getName()));
bf.registerBeanDefinition("mock", rbd);
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(1, beans.size());
}
@Test
public void parameterizedInstanceFactoryMethodWithIndexedArgument() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();