Browse Source

Consistent getTypeForFactoryMethod result for parameterized method

Issue: SPR-16720
pull/1776/merge
Juergen Hoeller 8 years ago
parent
commit
6184c4ecc9
  1. 16
      spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
  2. 47
      spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactoryGenericsTests.java

16
spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

@ -752,7 +752,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -752,7 +752,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
factoryMethod, args, getBeanClassLoader());
uniqueCandidate = (commonType == null ? factoryMethod : null);
uniqueCandidate = (commonType == null && returnType == factoryMethod.getReturnType() ?
factoryMethod : null);
commonType = ClassUtils.determineCommonAncestor(returnType, commonType);
if (commonType == null) {
// Ambiguous return types found: return null to indicate "not determinable".
@ -776,12 +777,15 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @@ -776,12 +777,15 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
}
if (commonType != null) {
// Clear return type found: all factory methods return same type.
mbd.factoryMethodReturnType = (uniqueCandidate != null ?
ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
if (commonType == null) {
return null;
}
return commonType;
// Common return type found: all factory methods return same type. For a non-parameterized
// unique candidate, cache the full type declaration context of the target factory method.
cachedReturnType = (uniqueCandidate != null ?
ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
mbd.factoryMethodReturnType = cachedReturnType;
return cachedReturnType.resolve();
}
/**

47
spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactoryGenericsTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 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.
@ -40,6 +40,7 @@ import org.springframework.beans.factory.BeanCreationException; @@ -40,6 +40,7 @@ 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.OverridingClassLoader;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.UrlResource;
@ -672,6 +673,8 @@ public class BeanFactoryGenericsTests { @@ -672,6 +673,8 @@ public class BeanFactoryGenericsTests {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("mock", rbd);
assertEquals(Runnable.class, bf.getType("mock"));
assertEquals(Runnable.class, bf.getType("mock"));
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(1, beans.size());
}
@ -700,6 +703,10 @@ public class BeanFactoryGenericsTests { @@ -700,6 +703,10 @@ public class BeanFactoryGenericsTests {
rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class);
bf.registerBeanDefinition("mock", rbd);
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertEquals(Runnable.class, bf.getType("mock"));
assertEquals(Runnable.class, bf.getType("mock"));
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(1, beans.size());
}
@ -717,6 +724,10 @@ public class BeanFactoryGenericsTests { @@ -717,6 +724,10 @@ public class BeanFactoryGenericsTests {
rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class.getName());
bf.registerBeanDefinition("mock", rbd);
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertEquals(Runnable.class, bf.getType("mock"));
assertEquals(Runnable.class, bf.getType("mock"));
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(1, beans.size());
}
@ -732,6 +743,10 @@ public class BeanFactoryGenericsTests { @@ -732,6 +743,10 @@ public class BeanFactoryGenericsTests {
rbd.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue(Runnable.class.getName()));
bf.registerBeanDefinition("mock", rbd);
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertEquals(Runnable.class, bf.getType("mock"));
assertEquals(Runnable.class, bf.getType("mock"));
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(1, beans.size());
}
@ -749,6 +764,10 @@ public class BeanFactoryGenericsTests { @@ -749,6 +764,10 @@ public class BeanFactoryGenericsTests {
rbd.getConstructorArgumentValues().addGenericArgumentValue("x");
bf.registerBeanDefinition("mock", rbd);
assertFalse(bf.isTypeMatch("mock", Runnable.class));
assertFalse(bf.isTypeMatch("mock", Runnable.class));
assertNull(bf.getType("mock"));
assertNull(bf.getType("mock"));
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(0, beans.size());
}
@ -766,6 +785,32 @@ public class BeanFactoryGenericsTests { @@ -766,6 +785,32 @@ public class BeanFactoryGenericsTests {
rbd.getConstructorArgumentValues().addIndexedArgumentValue(0, Runnable.class);
bf.registerBeanDefinition("mock", rbd);
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertEquals(Runnable.class, bf.getType("mock"));
assertEquals(Runnable.class, bf.getType("mock"));
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(1, beans.size());
}
@Test // SPR-16720
public void parameterizedInstanceFactoryMethodWithTempClassLoader() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setTempClassLoader(new OverridingClassLoader(getClass().getClassLoader()));
RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class);
bf.registerBeanDefinition("mocksControl", rbd);
rbd = new RootBeanDefinition();
rbd.setFactoryBeanName("mocksControl");
rbd.setFactoryMethodName("createMock");
rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class);
bf.registerBeanDefinition("mock", rbd);
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertTrue(bf.isTypeMatch("mock", Runnable.class));
assertEquals(Runnable.class, bf.getType("mock"));
assertEquals(Runnable.class, bf.getType("mock"));
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
assertEquals(1, beans.size());
}

Loading…
Cancel
Save