Use non-lenient constructor resolution mode for @Bean methods
Since @Bean methods are never used with externally specified constructor argument values but rather just with autowiring, the non-lenient constructor resolution mode is appropriate in case of an overloaded @Bean method, not performing any type difference weight checks. This change includes a refinement of Spring's existing non-lenient constructor resolution (which needs to be explicitly turned on and is therefore not well tested), narrowing the conditions for the ambiguity check (only in case of the same number of arguments and not for overridden methods). Issue: SPR-10988
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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,7 +40,7 @@ import java.lang.reflect.Modifier;
|
||||
*/
|
||||
public class MethodInvoker {
|
||||
|
||||
private Class targetClass;
|
||||
private Class<?> targetClass;
|
||||
|
||||
private Object targetObject;
|
||||
|
||||
@@ -61,14 +61,14 @@ public class MethodInvoker {
|
||||
* @see #setTargetObject
|
||||
* @see #setTargetMethod
|
||||
*/
|
||||
public void setTargetClass(Class targetClass) {
|
||||
public void setTargetClass(Class<?> targetClass) {
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target class on which to call the target method.
|
||||
*/
|
||||
public Class getTargetClass() {
|
||||
public Class<?> getTargetClass() {
|
||||
return this.targetClass;
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ public class MethodInvoker {
|
||||
this.targetMethod = methodName;
|
||||
}
|
||||
|
||||
Class targetClass = getTargetClass();
|
||||
Class<?> targetClass = getTargetClass();
|
||||
String targetMethod = getTargetMethod();
|
||||
if (targetClass == null) {
|
||||
throw new IllegalArgumentException("Either 'targetClass' or 'targetObject' is required");
|
||||
@@ -194,7 +194,7 @@ public class MethodInvoker {
|
||||
* @return the resolved Class
|
||||
* @throws ClassNotFoundException if the class name was invalid
|
||||
*/
|
||||
protected Class resolveClassName(String className) throws ClassNotFoundException {
|
||||
protected Class<?> resolveClassName(String className) throws ClassNotFoundException {
|
||||
return ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
|
||||
@@ -287,19 +287,22 @@ public class MethodInvoker {
|
||||
* Therefore, with an arg of type Integer, a constructor (Integer) would be preferred to a
|
||||
* constructor (Number) which would in turn be preferred to a constructor (Object).
|
||||
* All argument weights get accumulated.
|
||||
* <p>Note: This is the algorithm used by MethodInvoker itself and also the algorithm
|
||||
* used for constructor and factory method selection in Spring's bean container (in case
|
||||
* of lenient constructor resolution which is the default for regular bean definitions).
|
||||
* @param paramTypes the parameter types to match
|
||||
* @param args the arguments to match
|
||||
* @return the accumulated weight for all arguments
|
||||
*/
|
||||
public static int getTypeDifferenceWeight(Class[] paramTypes, Object[] args) {
|
||||
public static int getTypeDifferenceWeight(Class<?>[] paramTypes, Object[] args) {
|
||||
int result = 0;
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
if (!ClassUtils.isAssignableValue(paramTypes[i], args[i])) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
if (args[i] != null) {
|
||||
Class paramType = paramTypes[i];
|
||||
Class superClass = args[i].getClass().getSuperclass();
|
||||
Class<?> paramType = paramTypes[i];
|
||||
Class<?> superClass = args[i].getClass().getSuperclass();
|
||||
while (superClass != null) {
|
||||
if (paramType.equals(superClass)) {
|
||||
result = result + 2;
|
||||
|
||||
Reference in New Issue
Block a user