Name attributes in method argument annotations allow for placeholders and expressions

Issue: SPR-13952
This commit is contained in:
Juergen Hoeller
2016-02-17 22:59:12 +01:00
parent c2f704717e
commit e0d7c6be00
4 changed files with 115 additions and 70 deletions

View File

@@ -89,10 +89,16 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
MethodParameter nestedParameter = parameter.nestedIfOptional();
Object arg = resolveName(namedValueInfo.name, nestedParameter, webRequest);
Object resolvedName = resolveStringValue(namedValueInfo.name);
if (resolvedName == null) {
throw new IllegalArgumentException(
"Specified name must not resolve to null: [" + namedValueInfo.name + "]");
}
Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
if (arg == null) {
if (namedValueInfo.defaultValue != null) {
arg = resolveDefaultValue(namedValueInfo.defaultValue);
arg = resolveStringValue(namedValueInfo.defaultValue);
}
else if (namedValueInfo.required && !nestedParameter.isOptional()) {
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
@@ -100,7 +106,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
}
else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
arg = resolveDefaultValue(namedValueInfo.defaultValue);
arg = resolveStringValue(namedValueInfo.defaultValue);
}
if (binderFactory != null) {
@@ -162,6 +168,22 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
return new NamedValueInfo(name, info.required, defaultValue);
}
/**
* Resolve the given annotation-specified value,
* potentially containing placeholders and expressions.
*/
private Object resolveStringValue(String value) {
if (this.configurableBeanFactory == null) {
return value;
}
String placeholdersResolved = this.configurableBeanFactory.resolveEmbeddedValue(value);
BeanExpressionResolver exprResolver = this.configurableBeanFactory.getBeanExpressionResolver();
if (exprResolver == null) {
return value;
}
return exprResolver.evaluate(placeholdersResolved, this.expressionContext);
}
/**
* Resolve the given parameter type and value name into an argument value.
* @param name the name of the value being resolved
@@ -174,21 +196,6 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
protected abstract Object resolveName(String name, MethodParameter parameter, NativeWebRequest request)
throws Exception;
/**
* Resolve the given default value into an argument value.
*/
private Object resolveDefaultValue(String defaultValue) {
if (this.configurableBeanFactory == null) {
return defaultValue;
}
String placeholdersResolved = this.configurableBeanFactory.resolveEmbeddedValue(defaultValue);
BeanExpressionResolver exprResolver = this.configurableBeanFactory.getBeanExpressionResolver();
if (exprResolver == null) {
return defaultValue;
}
return exprResolver.evaluate(placeholdersResolved, this.expressionContext);
}
/**
* Invoked when a named value is required, but {@link #resolveName(String, MethodParameter, NativeWebRequest)}
* returned {@code null} and there is no default value. Subclasses typically throw an exception in this case.