Defensive handling of exceptions during factory method type checking
Also using ClassUtils.forName in AutowireUtils now in order to accept all common class name formats. Issue: SPR-11034
This commit is contained in:
parent
180f41c4c5
commit
8c1767e223
|
|
@ -667,33 +667,40 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
factoryMethod.getParameterTypes().length >= minNrOfArgs) {
|
||||
// No declared type variables to inspect, so just process the standard return type.
|
||||
if (factoryMethod.getTypeParameters().length > 0) {
|
||||
// Fully resolve parameter names and argument values.
|
||||
Class<?>[] paramTypes = factoryMethod.getParameterTypes();
|
||||
String[] paramNames = null;
|
||||
ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
|
||||
if (pnd != null) {
|
||||
paramNames = pnd.getParameterNames(factoryMethod);
|
||||
}
|
||||
ConstructorArgumentValues cav = mbd.getConstructorArgumentValues();
|
||||
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
|
||||
new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
|
||||
Object[] args = new Object[paramTypes.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue(
|
||||
i, paramTypes[i], (paramNames != null ? paramNames[i] : null), usedValueHolders);
|
||||
if (valueHolder == null) {
|
||||
valueHolder = cav.getGenericArgumentValue(null, null, usedValueHolders);
|
||||
try {
|
||||
// Fully resolve parameter names and argument values.
|
||||
Class<?>[] paramTypes = factoryMethod.getParameterTypes();
|
||||
String[] paramNames = null;
|
||||
ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
|
||||
if (pnd != null) {
|
||||
paramNames = pnd.getParameterNames(factoryMethod);
|
||||
}
|
||||
if (valueHolder != null) {
|
||||
args[i] = valueHolder.getValue();
|
||||
usedValueHolders.add(valueHolder);
|
||||
ConstructorArgumentValues cav = mbd.getConstructorArgumentValues();
|
||||
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
|
||||
new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
|
||||
Object[] args = new Object[paramTypes.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue(
|
||||
i, paramTypes[i], (paramNames != null ? paramNames[i] : null), usedValueHolders);
|
||||
if (valueHolder == null) {
|
||||
valueHolder = cav.getGenericArgumentValue(null, null, usedValueHolders);
|
||||
}
|
||||
if (valueHolder != null) {
|
||||
args[i] = valueHolder.getValue();
|
||||
usedValueHolders.add(valueHolder);
|
||||
}
|
||||
}
|
||||
Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
|
||||
factoryMethod, args, getBeanClassLoader());
|
||||
if (returnType != null) {
|
||||
cache = true;
|
||||
returnTypes.add(returnType);
|
||||
}
|
||||
}
|
||||
Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
|
||||
factoryMethod, args, getBeanClassLoader());
|
||||
if (returnType != null) {
|
||||
cache = true;
|
||||
returnTypes.add(returnType);
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to resolve generic return type for factory method: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,8 @@ abstract class AutowireUtils {
|
|||
return typedValue.resolveTargetType(classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException("Failed to resolve typed value", ex);
|
||||
throw new IllegalStateException("Failed to resolve value type [" +
|
||||
typedValue.getTargetTypeName() + "] for factory method argument", ex);
|
||||
}
|
||||
}
|
||||
// Only consider argument type if it is a simple value...
|
||||
|
|
@ -254,11 +255,11 @@ abstract class AutowireUtils {
|
|||
}
|
||||
if (className != null) {
|
||||
try {
|
||||
return classLoader.loadClass(className);
|
||||
return ClassUtils.forName(className, classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Could not resolve specified class name argument [" + arg + "]", ex);
|
||||
throw new IllegalStateException("Could not resolve class name [" + arg +
|
||||
"] for factory method argument", ex);
|
||||
}
|
||||
}
|
||||
// Consider adding logic to determine the class of the typeArg, if possible.
|
||||
|
|
|
|||
|
|
@ -735,6 +735,23 @@ public class BeanFactoryGenericsTests {
|
|||
assertEquals(1, beans.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterizedInstanceFactoryMethodWithInvalidClassName() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class);
|
||||
bf.registerBeanDefinition("mocksControl", rbd);
|
||||
|
||||
rbd = new RootBeanDefinition();
|
||||
rbd.setFactoryBeanName("mocksControl");
|
||||
rbd.setFactoryMethodName("createMock");
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue("x");
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(0, beans.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterizedInstanceFactoryMethodWithIndexedArgument() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
|
|
|
|||
Loading…
Reference in New Issue