Split between basic MethodParameter and SynthesizingMethodParameter

This split avoids a package tangle (between core and core.annotation) and also allows for selective use of raw annotation exposure versus synthesized annotations, with the latter primarily applicable to web and message handler processing at this point.

Issue: SPR-13153
This commit is contained in:
Juergen Hoeller 2015-06-30 00:02:02 +02:00
parent 26acb4887d
commit dc1f921f5c
24 changed files with 286 additions and 216 deletions

View File

@ -26,7 +26,6 @@ import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
/**
@ -34,6 +33,10 @@ import org.springframework.util.Assert;
* a Method or Constructor plus a parameter index and a nested type index for
* a declared generic type. Useful as a specification object to pass along.
*
* <p>As of 4.2, there is a {@link org.springframework.core.annotation.SynthesizingMethodParameter}
* subclass available which synthesizes annotations based on overridden annotation attributes.
* That subclass is being used for web and message endpoint processing, in particular.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @author Andy Clement
@ -388,7 +391,7 @@ public class MethodParameter {
* Return the annotations associated with the target method/constructor itself.
*/
public Annotation[] getMethodAnnotations() {
return AnnotationUtils.synthesizeAnnotationArray(getAnnotatedElement().getAnnotations(), getAnnotatedElement());
return adaptAnnotationArray(getAnnotatedElement().getAnnotations());
}
/**
@ -396,9 +399,8 @@ public class MethodParameter {
* @param annotationType the annotation type to look for
* @return the annotation object, or {@code null} if not found
*/
public <T extends Annotation> T getMethodAnnotation(Class<T> annotationType) {
AnnotatedElement element = getAnnotatedElement();
return AnnotationUtils.synthesizeAnnotation(element.getAnnotation(annotationType), element);
public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
return adaptAnnotation(getAnnotatedElement().getAnnotation(annotationType));
}
/**
@ -409,8 +411,7 @@ public class MethodParameter {
Annotation[][] annotationArray = (this.method != null ?
this.method.getParameterAnnotations() : this.constructor.getParameterAnnotations());
if (this.parameterIndex >= 0 && this.parameterIndex < annotationArray.length) {
this.parameterAnnotations = AnnotationUtils.synthesizeAnnotationArray(
annotationArray[this.parameterIndex], getAnnotatedElement());
this.parameterAnnotations = adaptAnnotationArray(annotationArray[this.parameterIndex]);
}
else {
this.parameterAnnotations = new Annotation[0];
@ -480,6 +481,31 @@ public class MethodParameter {
}
/**
* A template method to post-process a given annotation instance before
* returning it to the caller.
* <p>The default implementation simply returns the given annotation as-is.
* @param annotation the annotation about to be returned
* @return the post-processed annotation (or simply the original one)
* @since 4.2
*/
protected <A extends Annotation> A adaptAnnotation(A annotation) {
return annotation;
}
/**
* A template method to post-process a given annotation array before
* returning it to the caller.
* <p>The default implementation simply returns the given annotation array as-is.
* @param annotations the annotation array about to be returned
* @return the post-processed annotation array (or simply the original one)
* @since 4.2
*/
protected Annotation[] adaptAnnotationArray(Annotation[] annotations) {
return annotations;
}
@Override
public boolean equals(Object other) {
if (this == other) {

View File

@ -1122,7 +1122,7 @@ public class ResolvableType implements Serializable {
*/
public static ResolvableType forMethodReturnType(Method method) {
Assert.notNull(method, "Method must not be null");
return forMethodParameter(MethodParameter.forMethodOrConstructor(method, -1));
return forMethodParameter(new MethodParameter(method, -1));
}
/**
@ -1136,7 +1136,7 @@ public class ResolvableType implements Serializable {
*/
public static ResolvableType forMethodReturnType(Method method, Class<?> implementationClass) {
Assert.notNull(method, "Method must not be null");
MethodParameter methodParameter = MethodParameter.forMethodOrConstructor(method, -1);
MethodParameter methodParameter = new MethodParameter(method, -1);
methodParameter.setContainingClass(implementationClass);
return forMethodParameter(methodParameter);
}

View File

@ -266,6 +266,7 @@ public abstract class AnnotationUtils {
@Deprecated
public static <A extends Annotation> Set<A> getRepeatableAnnotation(Method method,
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
return getRepeatableAnnotations(method, annotationType, containerAnnotationType);
}
@ -280,6 +281,7 @@ public abstract class AnnotationUtils {
@Deprecated
public static <A extends Annotation> Set<A> getRepeatableAnnotation(AnnotatedElement annotatedElement,
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
return getRepeatableAnnotations(annotatedElement, annotationType, containerAnnotationType);
}
@ -311,6 +313,7 @@ public abstract class AnnotationUtils {
*/
public static <A extends Annotation> Set<A> getRepeatableAnnotations(AnnotatedElement annotatedElement,
Class<A> annotationType) {
return getRepeatableAnnotations(annotatedElement, annotationType, null);
}
@ -353,7 +356,7 @@ public abstract class AnnotationUtils {
if (annotatedElement instanceof Class) {
Class<?> superclass = ((Class<?>) annotatedElement).getSuperclass();
if ((superclass != null) && (Object.class != superclass)) {
if (superclass != null && Object.class != superclass) {
return getRepeatableAnnotations(superclass, annotationType, containerAnnotationType);
}
}
@ -434,7 +437,6 @@ public abstract class AnnotationUtils {
* compiler if the supplied element is a {@link Method}.
* <p>Meta-annotations will be searched if the annotation is not
* <em>present</em> on the supplied element.
*
* @param annotatedElement the element to look for annotations on; never {@code null}
* @param annotationType the annotation type to look for; never {@code null}
* @param containerAnnotationType the type of the container that holds
@ -955,10 +957,8 @@ public abstract class AnnotationUtils {
/**
* Retrieve the given annotation's attributes as an {@link AnnotationAttributes} map.
*
* <p>This method provides fully recursive annotation reading capabilities on par with
* the reflection-based {@link org.springframework.core.type.StandardAnnotationMetadata}.
*
* <p><strong>NOTE</strong>: This variant of {@code getAnnotationAttributes()} is
* only intended for use within the framework. Specifically, the {@code mergeMode} flag
* can be set to {@code true} in order to support processing of attribute aliases while
@ -975,7 +975,6 @@ public abstract class AnnotationUtils {
* ensure that placeholders have been replaced by actual default values and
* in order to enforce {@code @AliasFor} semantics.</li>
* </ol>
*
* @param annotatedElement the element that is annotated with the supplied annotation;
* may be {@code null} if unknown
* @param annotation the annotation to retrieve the attributes for
@ -1062,8 +1061,7 @@ public abstract class AnnotationUtils {
Annotation annotation = (Annotation) value;
if (nestedAnnotationsAsMap) {
return getAnnotationAttributes(annotatedElement, annotation, classValuesAsString,
nestedAnnotationsAsMap);
return getAnnotationAttributes(annotatedElement, annotation, classValuesAsString, true);
}
else {
return synthesizeAnnotation(annotation, annotatedElement);
@ -1077,7 +1075,7 @@ public abstract class AnnotationUtils {
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[annotations.length];
for (int i = 0; i < annotations.length; i++) {
mappedAnnotations[i] = getAnnotationAttributes(annotatedElement, annotations[i],
classValuesAsString, nestedAnnotationsAsMap);
classValuesAsString, true);
}
return mappedAnnotations;
}
@ -1183,7 +1181,6 @@ public abstract class AnnotationUtils {
* by wrapping it in a dynamic proxy that transparently enforces
* <em>attribute alias</em> semantics for annotation attributes that are
* annotated with {@link AliasFor @AliasFor}.
*
* @param annotation the annotation to synthesize
* @return the synthesized annotation, if the supplied annotation is
* <em>synthesizable</em>; {@code null} if the supplied annotation is
@ -1202,7 +1199,6 @@ public abstract class AnnotationUtils {
* by wrapping it in a dynamic proxy that transparently enforces
* <em>attribute alias</em> semantics for annotation attributes that are
* annotated with {@link AliasFor @AliasFor}.
*
* @param annotation the annotation to synthesize
* @param annotatedElement the element that is annotated with the supplied
* annotation; may be {@code null} if unknown
@ -1229,11 +1225,11 @@ public abstract class AnnotationUtils {
return annotation;
}
AnnotationAttributeExtractor attributeExtractor = new DefaultAnnotationAttributeExtractor(annotation,
annotatedElement);
AnnotationAttributeExtractor attributeExtractor =
new DefaultAnnotationAttributeExtractor(annotation, annotatedElement);
InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);
A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), new Class<?>[] {
(Class<A>) annotationType, SynthesizedAnnotation.class }, handler);
A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(),
new Class<?>[] {(Class<A>) annotationType, SynthesizedAnnotation.class}, handler);
return synthesizedAnnotation;
}
@ -1250,7 +1246,6 @@ public abstract class AnnotationUtils {
* <p>Note that {@link AnnotationAttributes} is a specialized type of
* {@link Map} that is an ideal candidate for this method's
* {@code attributes} argument.
*
* @param attributes the map of annotation attributes to synthesize
* @param annotationType the type of annotation to synthesize; never {@code null}
* @param annotatedElement the element that is annotated with the annotation
@ -1268,17 +1263,17 @@ public abstract class AnnotationUtils {
@SuppressWarnings("unchecked")
public static <A extends Annotation> A synthesizeAnnotation(Map<String, Object> attributes,
Class<A> annotationType, AnnotatedElement annotatedElement) {
Assert.notNull(annotationType, "annotationType must not be null");
Assert.notNull(annotationType, "annotationType must not be null");
if (attributes == null) {
return null;
}
AnnotationAttributeExtractor attributeExtractor = new MapAnnotationAttributeExtractor(attributes,
annotationType, annotatedElement);
AnnotationAttributeExtractor attributeExtractor =
new MapAnnotationAttributeExtractor(attributes, annotationType, annotatedElement);
InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);
A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), new Class<?>[] {
annotationType, SynthesizedAnnotation.class }, handler);
A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(),
new Class<?>[] {annotationType, SynthesizedAnnotation.class}, handler);
return synthesizedAnnotation;
}
@ -1289,7 +1284,6 @@ public abstract class AnnotationUtils {
* {@link #synthesizeAnnotation(Map, Class, AnnotatedElement)},
* supplying an empty map for the source attribute values and {@code null}
* for the {@link AnnotatedElement}.
*
* @param annotationType the type of annotation to synthesize; never {@code null}
* @return the synthesized annotation
* @throws IllegalArgumentException if a required attribute is missing
@ -1308,7 +1302,6 @@ public abstract class AnnotationUtils {
* creating a new array of the same size and type and populating it
* with {@linkplain #synthesizeAnnotation(Annotation) synthesized}
* versions of the annotations from the input array.
*
* @param annotations the array of annotations to synthesize
* @param annotatedElement the element that is annotated with the supplied
* array of annotations; may be {@code null} if unknown
@ -1325,7 +1318,8 @@ public abstract class AnnotationUtils {
return null;
}
Annotation[] synthesized = (Annotation[]) Array.newInstance(annotations.getClass().getComponentType(), annotations.length);
Annotation[] synthesized = (Annotation[]) Array.newInstance(
annotations.getClass().getComponentType(), annotations.length);
for (int i = 0; i < annotations.length; i++) {
synthesized[i] = synthesizeAnnotation(annotations[i], annotatedElement);
}
@ -1335,14 +1329,11 @@ public abstract class AnnotationUtils {
/**
* Get a map of all attribute alias pairs, declared via {@code @AliasFor}
* in the supplied annotation type.
*
* <p>The map is keyed by attribute name with each value representing
* the name of the aliased attribute. For each entry {@code [x, y]} in
* the map there will be a corresponding {@code [y, x]} entry in the map.
*
* <p>An empty return value implies that the annotation does not declare
* any attribute aliases.
*
* @param annotationType the annotation type to find attribute aliases in
* @return a map containing attribute alias pairs; never {@code null}
* @since 4.2
@ -1376,34 +1367,28 @@ public abstract class AnnotationUtils {
* <em>synthesizable</em> (i.e., in need of being wrapped in a dynamic
* proxy that provides functionality above that of a standard JDK
* annotation).
*
* <p>Specifically, an annotation is <em>synthesizable</em> if it declares
* any attributes that are configured as <em>aliased pairs</em> via
* {@link AliasFor @AliasFor} or if any nested annotations used by the
* annotation declare such <em>aliased pairs</em>.
*
* @since 4.2
* @see SynthesizedAnnotation
* @see SynthesizedAnnotationInvocationHandler
*/
@SuppressWarnings("unchecked")
private static boolean isSynthesizable(Class<? extends Annotation> annotationType) {
Boolean synthesizable = synthesizableCache.get(annotationType);
if (synthesizable != null) {
return synthesizable.booleanValue();
}
synthesizable = Boolean.FALSE;
for (Method attribute : getAttributeMethods(annotationType)) {
if (getAliasedAttributeName(attribute) != null) {
synthesizable = Boolean.TRUE;
break;
}
Class<?> returnType = attribute.getReturnType();
if (Annotation[].class.isAssignableFrom(returnType)) {
Class<? extends Annotation> nestedAnnotationType = (Class<? extends Annotation>) returnType.getComponentType();
if (isSynthesizable(nestedAnnotationType)) {
@ -1421,20 +1406,17 @@ public abstract class AnnotationUtils {
}
synthesizableCache.put(annotationType, synthesizable);
return synthesizable.booleanValue();
}
/**
* Get the name of the aliased attribute configured via
* {@link AliasFor @AliasFor} on the supplied annotation {@code attribute}.
*
* <p>This method does not resolve aliases in other annotations. In
* other words, if {@code @AliasFor} is present on the supplied
* {@code attribute} but {@linkplain AliasFor#annotation references an
* annotation} other than {@link Annotation}, this method will return
* {@code null} immediately.
*
* @param attribute the attribute to find an alias for
* @return the name of the aliased attribute, or {@code null} if not found
* @throws IllegalArgumentException if the supplied attribute method is
@ -1451,7 +1433,6 @@ public abstract class AnnotationUtils {
/**
* Get the name of the aliased attribute configured via
* {@link AliasFor @AliasFor} on the supplied annotation {@code attribute}.
*
* @param attribute the attribute to find an alias for
* @param targetAnnotationType the type of annotation in which the
* aliased attribute is allowed to be declared; {@code null} implies
@ -1481,7 +1462,8 @@ public abstract class AnnotationUtils {
Class<? extends Annotation> aliasedAnnotationType = aliasFor.annotation();
boolean searchWithinSameAnnotation = (targetAnnotationType == null);
boolean sameTargetDeclared = (sourceAnnotationType.equals(aliasedAnnotationType) || Annotation.class.equals(aliasedAnnotationType));
boolean sameTargetDeclared =
(sourceAnnotationType.equals(aliasedAnnotationType) || Annotation.class.equals(aliasedAnnotationType));
// Wrong search scope?
if (searchWithinSameAnnotation && !sameTargetDeclared) {
@ -1502,30 +1484,30 @@ public abstract class AnnotationUtils {
aliasedAnnotationType = sourceAnnotationType;
}
Method aliasedAttribute = null;
Method aliasedAttribute;
try {
aliasedAttribute = aliasedAnnotationType.getDeclaredMethod(aliasedAttributeName);
}
catch (NoSuchMethodException e) {
catch (NoSuchMethodException ex) {
String msg = String.format(
"Attribute [%s] in annotation [%s] is declared as an @AliasFor nonexistent attribute [%s] in annotation [%s].",
attributeName, sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
throw new AnnotationConfigurationException(msg, e);
"Attribute [%s] in annotation [%s] is declared as an @AliasFor nonexistent attribute [%s] in annotation [%s].",
attributeName, sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
throw new AnnotationConfigurationException(msg, ex);
}
if (sameTargetDeclared) {
AliasFor mirrorAliasFor = aliasedAttribute.getAnnotation(AliasFor.class);
if (mirrorAliasFor == null) {
String msg = String.format("Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s].",
aliasedAttributeName, sourceAnnotationType.getName(), attributeName);
aliasedAttributeName, sourceAnnotationType.getName(), attributeName);
throw new AnnotationConfigurationException(msg);
}
String mirrorAliasedAttributeName = mirrorAliasFor.attribute();
if (!attributeName.equals(mirrorAliasedAttributeName)) {
String msg = String.format(
"Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s], not [%s].",
aliasedAttributeName, sourceAnnotationType.getName(), attributeName, mirrorAliasedAttributeName);
"Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s], not [%s].",
aliasedAttributeName, sourceAnnotationType.getName(), attributeName, mirrorAliasedAttributeName);
throw new AnnotationConfigurationException(msg);
}
}
@ -1533,9 +1515,9 @@ public abstract class AnnotationUtils {
Class<?> returnType = attribute.getReturnType();
Class<?> aliasedReturnType = aliasedAttribute.getReturnType();
if (!returnType.equals(aliasedReturnType)) {
String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] "
+ "and attribute [%s] in annotation [%s] must declare the same return type.", attributeName,
sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " +
"and attribute [%s] in annotation [%s] must declare the same return type.", attributeName,
sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
throw new AnnotationConfigurationException(msg);
}
@ -1544,16 +1526,16 @@ public abstract class AnnotationUtils {
Object aliasedDefaultValue = aliasedAttribute.getDefaultValue();
if ((defaultValue == null) || (aliasedDefaultValue == null)) {
String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] "
+ "and attribute [%s] in annotation [%s] must declare default values.", attributeName,
sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " +
"and attribute [%s] in annotation [%s] must declare default values.", attributeName,
sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
throw new AnnotationConfigurationException(msg);
}
if (!ObjectUtils.nullSafeEquals(defaultValue, aliasedDefaultValue)) {
String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] "
+ "and attribute [%s] in annotation [%s] must declare the same default value.", attributeName,
sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " +
"and attribute [%s] in annotation [%s] must declare the same default value.", attributeName,
sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName());
throw new AnnotationConfigurationException(msg);
}
}
@ -1564,10 +1546,8 @@ public abstract class AnnotationUtils {
/**
* Get all methods declared in the supplied {@code annotationType} that
* match Java's requirements for annotation <em>attributes</em>.
*
* <p>All methods in the returned list will be
* {@linkplain ReflectionUtils#makeAccessible(Method) made accessible}.
*
* @param annotationType the type in which to search for attribute methods;
* never {@code null}
* @return all annotation attribute methods in the specified annotation
@ -1575,7 +1555,6 @@ public abstract class AnnotationUtils {
* @since 4.2
*/
static List<Method> getAttributeMethods(Class<? extends Annotation> annotationType) {
List<Method> methods = attributeMethodsCache.get(annotationType);
if (methods != null) {
return methods;
@ -1590,7 +1569,6 @@ public abstract class AnnotationUtils {
}
attributeMethodsCache.put(annotationType, methods);
return methods;
}
@ -1618,7 +1596,7 @@ public abstract class AnnotationUtils {
* @return {@code true} if the method is an attribute method
*/
static boolean isAttributeMethod(Method method) {
return ((method != null) && (method.getParameterTypes().length == 0) && (method.getReturnType() != void.class));
return (method != null && method.getParameterTypes().length == 0 && method.getReturnType() != void.class);
}
/**
@ -1627,17 +1605,15 @@ public abstract class AnnotationUtils {
* @see Annotation#annotationType()
*/
static boolean isAnnotationTypeMethod(Method method) {
return ((method != null) && method.getName().equals("annotationType") && (method.getParameterTypes().length == 0));
return (method != null && method.getName().equals("annotationType") && method.getParameterTypes().length == 0);
}
/**
* Post-process the supplied {@link AnnotationAttributes}.
*
* <p>Specifically, this method enforces <em>attribute alias</em> semantics
* for annotation attributes that are annotated with {@link AliasFor @AliasFor}
* and replaces {@linkplain #DEFAULT_VALUE_PLACEHOLDER placeholders} with their
* original default values.
*
* @param element the element that is annotated with an annotation or
* annotation hierarchy from which the supplied attributes were created;
* may be {@code null} if unknown
@ -1715,9 +1691,9 @@ public abstract class AnnotationUtils {
* @param t the throwable to inspect
* @since 4.2
*/
static void rethrowAnnotationConfigurationException(Throwable t) {
if (t instanceof AnnotationConfigurationException) {
throw (AnnotationConfigurationException) t;
static void rethrowAnnotationConfigurationException(Throwable ex) {
if (ex instanceof AnnotationConfigurationException) {
throw (AnnotationConfigurationException) ex;
}
}
@ -1731,13 +1707,11 @@ public abstract class AnnotationUtils {
* Class values were not resolvable within annotation attributes and
* thereby effectively pretending there were no annotations on the specified
* element.
*
* @param element the element that we tried to introspect annotations on
* @param ex the exception that we encountered
* @see #rethrowAnnotationConfigurationException
*/
static void handleIntrospectionFailure(AnnotatedElement element, Exception ex) {
rethrowAnnotationConfigurationException(ex);
Log loggerToUse = logger;
@ -1745,7 +1719,7 @@ public abstract class AnnotationUtils {
loggerToUse = LogFactory.getLog(AnnotationUtils.class);
logger = loggerToUse;
}
if ((element instanceof Class) && Annotation.class.isAssignableFrom((Class<?>) element)) {
if (element instanceof Class && Annotation.class.isAssignableFrom((Class<?>) element)) {
// Meta-annotation lookup on an annotation type
if (loggerToUse.isDebugEnabled()) {
loggerToUse.debug("Failed to introspect meta-annotations on [" + element + "]: " + ex);
@ -1798,7 +1772,6 @@ public abstract class AnnotationUtils {
private static final String REPEATABLE_CLASS_NAME = "java.lang.annotation.Repeatable";
private final Class<A> annotationType;
private final Class<? extends Annotation> containerAnnotationType;
@ -1809,17 +1782,13 @@ public abstract class AnnotationUtils {
private final Set<A> result = new LinkedHashSet<A>();
AnnotationCollector(Class<A> annotationType, Class<? extends Annotation> containerAnnotationType, boolean declaredMode) {
this.annotationType = annotationType;
this.containerAnnotationType = (containerAnnotationType != null ? containerAnnotationType
: resolveContainerAnnotationType(annotationType));
this.containerAnnotationType = (containerAnnotationType != null ? containerAnnotationType :
resolveContainerAnnotationType(annotationType));
this.declaredMode = declaredMode;
}
/**
* @since 4.2
*/
@SuppressWarnings("unchecked")
static Class<? extends Annotation> resolveContainerAnnotationType(Class<? extends Annotation> annotationType) {
try {
@ -1829,8 +1798,8 @@ public abstract class AnnotationUtils {
return (Class<? extends Annotation>) value;
}
}
catch (Exception e) {
handleIntrospectionFailure(annotationType, e);
catch (Exception ex) {
handleIntrospectionFailure(annotationType, ex);
}
return null;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright 2002-2015 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.core.MethodParameter;
/**
* A {@link MethodParameter} variant which synthesizes annotations
* based on overridden annotation attributes, e.g. as declared with
* {@link AliasFor @AliasFor}.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 4.2
* @see AnnotationUtils#synthesizeAnnotation
* @see AnnotationUtils#synthesizeAnnotationArray
*/
public class SynthesizingMethodParameter extends MethodParameter {
/**
* Create a new {@code SynthesizingMethodParameter} for the given method.
* @param method the Method to specify a parameter for
* @param parameterIndex the index of the parameter: -1 for the method
* return type; 0 for the first method parameter; 1 for the second method
* parameter, etc.
*/
public SynthesizingMethodParameter(Method method, int parameterIndex) {
super(method, parameterIndex);
}
@Override
protected <A extends Annotation> A adaptAnnotation(A annotation) {
return AnnotationUtils.synthesizeAnnotation(annotation, getAnnotatedElement());
}
@Override
protected Annotation[] adaptAnnotationArray(Annotation[] annotations) {
return AnnotationUtils.synthesizeAnnotationArray(annotations, getAnnotatedElement());
}
}

View File

@ -26,6 +26,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -258,7 +259,7 @@ public class HandlerMethod {
/**
* A MethodParameter with HandlerMethod-specific behavior.
*/
protected class HandlerMethodParameter extends MethodParameter {
protected class HandlerMethodParameter extends SynthesizingMethodParameter {
public HandlerMethodParameter(int index) {
super(HandlerMethod.this.bridgedMethod, index);

View File

@ -27,6 +27,7 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
@ -62,16 +63,17 @@ public class HeaderMethodArgumentResolverTests {
Method method = getClass().getDeclaredMethod("handleMessage",
String.class, String.class, String.class, String.class, String.class);
this.paramRequired = new MethodParameter(method, 0);
this.paramNamedDefaultValueStringHeader = new MethodParameter(method, 1);
this.paramSystemProperty = new MethodParameter(method, 2);
this.paramNotAnnotated = new MethodParameter(method, 3);
this.paramNativeHeader = new MethodParameter(method, 4);
this.paramRequired = new SynthesizingMethodParameter(method, 0);
this.paramNamedDefaultValueStringHeader = new SynthesizingMethodParameter(method, 1);
this.paramSystemProperty = new SynthesizingMethodParameter(method, 2);
this.paramNotAnnotated = new SynthesizingMethodParameter(method, 3);
this.paramNativeHeader = new SynthesizingMethodParameter(method, 4);
this.paramRequired.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
GenericTypeResolver.resolveParameterType(this.paramRequired, HeaderMethodArgumentResolver.class);
}
@Test
public void supportsParameter() {
assertTrue(resolver.supportsParameter(paramNamedDefaultValueStringHeader));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -30,12 +30,12 @@ import org.junit.rules.ExpectedException;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.messaging.Message;
import org.springframework.messaging.converter.MessageConversionException;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.Assert;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
@ -80,14 +80,14 @@ public class PayloadArgumentResolverTests {
this.payloadMethod = PayloadArgumentResolverTests.class.getDeclaredMethod("handleMessage",
String.class, String.class, Locale.class, String.class, String.class, String.class, String.class);
this.paramAnnotated = getMethodParameter(this.payloadMethod, 0);
this.paramAnnotatedNotRequired = getMethodParameter(this.payloadMethod, 1);
this.paramAnnotatedRequired = getMethodParameter(payloadMethod, 2);
this.paramWithSpelExpression = getMethodParameter(payloadMethod, 3);
this.paramValidated = getMethodParameter(this.payloadMethod, 4);
this.paramAnnotated = new SynthesizingMethodParameter(this.payloadMethod, 0);
this.paramAnnotatedNotRequired = new SynthesizingMethodParameter(this.payloadMethod, 1);
this.paramAnnotatedRequired = new SynthesizingMethodParameter(payloadMethod, 2);
this.paramWithSpelExpression = new SynthesizingMethodParameter(payloadMethod, 3);
this.paramValidated = new SynthesizingMethodParameter(this.payloadMethod, 4);
this.paramValidated.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
this.paramValidatedNotAnnotated = getMethodParameter(this.payloadMethod, 5);
this.paramNotAnnotated = getMethodParameter(this.payloadMethod, 6);
this.paramValidatedNotAnnotated = new SynthesizingMethodParameter(this.payloadMethod, 5);
this.paramNotAnnotated = new SynthesizingMethodParameter(this.payloadMethod, 6);
}
@ -204,10 +204,6 @@ public class PayloadArgumentResolverTests {
};
}
private MethodParameter getMethodParameter(Method method, int index) {
Assert.notNull(method, "Method must be set");
return new MethodParameter(method, index);
}
@SuppressWarnings("unused")
private void handleMessage(

View File

@ -16,20 +16,17 @@
package org.springframework.messaging.simp.annotation.support;
import com.fasterxml.jackson.annotation.JsonView;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.security.auth.Subject;
import com.fasterxml.jackson.annotation.JsonView;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
@ -37,6 +34,7 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
@ -56,7 +54,7 @@ import org.springframework.util.MimeType;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver.DESTINATION_TEMPLATE_VARIABLES_HEADER;
import static org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver.*;
import static org.springframework.messaging.support.MessageHeaderAccessor.*;
/**
@ -95,7 +93,6 @@ public class SendToMethodReturnValueHandlerTests {
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
SimpMessagingTemplate messagingTemplate = new SimpMessagingTemplate(this.messageChannel);
@ -108,31 +105,31 @@ public class SendToMethodReturnValueHandlerTests {
this.jsonHandler = new SendToMethodReturnValueHandler(jsonMessagingTemplate, true);
Method method = this.getClass().getDeclaredMethod("handleNoAnnotations");
this.noAnnotationsReturnType = new MethodParameter(method, -1);
this.noAnnotationsReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToDefaultDestination");
this.sendToDefaultDestReturnType = new MethodParameter(method, -1);
this.sendToDefaultDestReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendTo");
this.sendToReturnType = new MethodParameter(method, -1);
this.sendToReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToWithPlaceholders");
this.sendToWithPlaceholdersReturnType = new MethodParameter(method, -1);
this.sendToWithPlaceholdersReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToUser");
this.sendToUserReturnType = new MethodParameter(method, -1);
this.sendToUserReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToUserSingleSession");
this.sendToUserSingleSessionReturnType = new MethodParameter(method, -1);
this.sendToUserSingleSessionReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToUserDefaultDestination");
this.sendToUserDefaultDestReturnType = new MethodParameter(method, -1);
this.sendToUserDefaultDestReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToUserDefaultDestinationSingleSession");
this.sendToUserSingleSessionDefaultDestReturnType = new MethodParameter(method, -1);
this.sendToUserSingleSessionDefaultDestReturnType = new SynthesizingMethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToJsonView");
this.jsonViewReturnType = new MethodParameter(method, -1);
this.jsonViewReturnType = new SynthesizingMethodParameter(method, -1);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -43,6 +43,7 @@ import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
@ -241,7 +242,7 @@ public class HandlerMethodInvoker {
Object[] args = new Object[paramTypes.length];
for (int i = 0; i < args.length; i++) {
MethodParameter methodParam = new MethodParameter(handlerMethod, i);
MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i);
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
String paramName = null;
@ -420,7 +421,7 @@ public class HandlerMethodInvoker {
Object[] initBinderArgs = new Object[initBinderParams.length];
for (int i = 0; i < initBinderArgs.length; i++) {
MethodParameter methodParam = new MethodParameter(initBinderMethod, i);
MethodParameter methodParam = new SynthesizingMethodParameter(initBinderMethod, i);
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
String paramName = null;

View File

@ -26,6 +26,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -268,7 +269,7 @@ public class HandlerMethod {
/**
* A MethodParameter with HandlerMethod-specific behavior.
*/
protected class HandlerMethodParameter extends MethodParameter {
protected class HandlerMethodParameter extends SynthesizingMethodParameter {
public HandlerMethodParameter(int index) {
super(HandlerMethod.this.bridgedMethod, index);

View File

@ -55,8 +55,8 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestHeader.class) &&
!Map.class.isAssignableFrom(parameter.getParameterType());
return (parameter.hasParameterAnnotation(RequestHeader.class) &&
!Map.class.isAssignableFrom(parameter.getParameterType()));
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@ -117,16 +117,16 @@ public class CompositeUriComponentsContributor implements UriComponentsContribut
public void contributeMethodArgument(MethodParameter parameter, Object value,
UriComponentsBuilder builder, Map<String, Object> uriVariables, ConversionService conversionService) {
for (Object c : this.contributors) {
if (c instanceof UriComponentsContributor) {
UriComponentsContributor contributor = (UriComponentsContributor) c;
if (contributor.supportsParameter(parameter)) {
contributor.contributeMethodArgument(parameter, value, builder, uriVariables, conversionService);
for (Object contributor : this.contributors) {
if (contributor instanceof UriComponentsContributor) {
UriComponentsContributor ucc = (UriComponentsContributor) contributor;
if (ucc.supportsParameter(parameter)) {
ucc.contributeMethodArgument(parameter, value, builder, uriVariables, conversionService);
break;
}
}
else if (c instanceof HandlerMethodArgumentResolver) {
if (((HandlerMethodArgumentResolver) c).supportsParameter(parameter)) {
else if (contributor instanceof HandlerMethodArgumentResolver) {
if (((HandlerMethodArgumentResolver) contributor).supportsParameter(parameter)) {
break;
}
}

View File

@ -23,6 +23,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.web.bind.ServletRequestBindingException;
@ -52,19 +53,21 @@ public class CookieValueMethodArgumentResolverTests {
private MockHttpServletRequest request;
@Before
public void setUp() throws Exception {
resolver = new TestCookieValueMethodArgumentResolver();
Method method = getClass().getMethod("params", Cookie.class, String.class, String.class);
paramNamedCookie = new MethodParameter(method, 0);
paramNamedDefaultValueString = new MethodParameter(method, 1);
paramString = new MethodParameter(method, 2);
paramNamedCookie = new SynthesizingMethodParameter(method, 0);
paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 1);
paramString = new SynthesizingMethodParameter(method, 2);
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
}
@Test
public void supportsParameter() {
assertTrue("Cookie parameter not supported", resolver.supportsParameter(paramNamedCookie));
@ -98,9 +101,10 @@ public class CookieValueMethodArgumentResolverTests {
}
}
public void params(@CookieValue("name") Cookie param1,
@CookieValue(name = "name", defaultValue = "bar") String param2,
String param3) {
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
@ -57,20 +58,22 @@ public class RequestHeaderMapMethodArgumentResolverTests {
private MockHttpServletRequest request;
@Before
public void setUp() throws Exception {
resolver = new RequestHeaderMapMethodArgumentResolver();
Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, HttpHeaders.class, Map.class);
paramMap = new MethodParameter(method, 0);
paramMultiValueMap = new MethodParameter(method, 1);
paramHttpHeaders = new MethodParameter(method, 2);
paramUnsupported = new MethodParameter(method, 3);
paramMap = new SynthesizingMethodParameter(method, 0);
paramMultiValueMap = new SynthesizingMethodParameter(method, 1);
paramHttpHeaders = new SynthesizingMethodParameter(method, 2);
paramUnsupported = new SynthesizingMethodParameter(method, 3);
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
}
@Test
public void supportsParameter() {
assertTrue("Map parameter not supported", resolver.supportsParameter(paramMap));
@ -130,10 +133,11 @@ public class RequestHeaderMapMethodArgumentResolverTests {
assertEquals("Invalid result", expected, result);
}
public void params(@RequestHeader Map<?, ?> param1,
@RequestHeader MultiValueMap<?, ?> param2,
@RequestHeader HttpHeaders param3,
Map<?,?> unsupported) {
}
}
}

View File

@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.web.bind.ServletRequestBindingException;
@ -55,6 +56,7 @@ public class RequestHeaderMethodArgumentResolverTests {
private NativeWebRequest webRequest;
@Before
public void setUp() throws Exception {
GenericWebApplicationContext context = new GenericWebApplicationContext();
@ -62,11 +64,11 @@ public class RequestHeaderMethodArgumentResolverTests {
resolver = new RequestHeaderMethodArgumentResolver(context.getBeanFactory());
Method method = getClass().getMethod("params", String.class, String[].class, String.class, String.class, Map.class);
paramNamedDefaultValueStringHeader = new MethodParameter(method, 0);
paramNamedValueStringArray = new MethodParameter(method, 1);
paramSystemProperty = new MethodParameter(method, 2);
paramContextPath = new MethodParameter(method, 3);
paramNamedValueMap = new MethodParameter(method, 4);
paramNamedDefaultValueStringHeader = new SynthesizingMethodParameter(method, 0);
paramNamedValueStringArray = new SynthesizingMethodParameter(method, 1);
paramSystemProperty = new SynthesizingMethodParameter(method, 2);
paramContextPath = new SynthesizingMethodParameter(method, 3);
paramNamedValueMap = new SynthesizingMethodParameter(method, 4);
servletRequest = new MockHttpServletRequest();
webRequest = new ServletWebRequest(servletRequest, new MockHttpServletResponse());
@ -80,6 +82,7 @@ public class RequestHeaderMethodArgumentResolverTests {
RequestContextHolder.resetRequestAttributes();
}
@Test
public void supportsParameter() {
assertTrue("String parameter not supported", resolver.supportsParameter(paramNamedDefaultValueStringHeader));
@ -141,6 +144,7 @@ public class RequestHeaderMethodArgumentResolverTests {
resolver.resolveArgument(paramNamedValueStringArray, null, webRequest, null);
}
public void params(@RequestHeader(name = "name", defaultValue = "bar") String param1,
@RequestHeader("name") String[] param2,
@RequestHeader(name = "name", defaultValue="#{systemProperties.systemProperty}") String param3,
@ -148,4 +152,4 @@ public class RequestHeaderMethodArgumentResolverTests {
@RequestHeader("name") Map<?, ?> unsupported) {
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.util.LinkedMultiValueMap;
@ -56,20 +57,22 @@ public class RequestParamMapMethodArgumentResolverTests {
private MockHttpServletRequest request;
@Before
public void setUp() throws Exception {
resolver = new RequestParamMapMethodArgumentResolver();
Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, Map.class, Map.class);
paramMap = new MethodParameter(method, 0);
paramMultiValueMap = new MethodParameter(method, 1);
paramNamedMap = new MethodParameter(method, 2);
paramMapWithoutAnnot = new MethodParameter(method, 3);
paramMap = new SynthesizingMethodParameter(method, 0);
paramMultiValueMap = new SynthesizingMethodParameter(method, 1);
paramNamedMap = new SynthesizingMethodParameter(method, 2);
paramMapWithoutAnnot = new SynthesizingMethodParameter(method, 3);
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
}
@Test
public void supportsParameter() {
assertTrue("Map parameter not supported", resolver.supportsParameter(paramMap));
@ -108,10 +111,11 @@ public class RequestParamMapMethodArgumentResolverTests {
assertEquals("Invalid result", expected, result);
}
public void params(@RequestParam Map<?, ?> param1,
@RequestParam MultiValueMap<?, ?> param2,
@RequestParam("name") Map<?, ?> param3,
Map<?, ?> param4) {
}
}
}

View File

@ -21,7 +21,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.servlet.http.Part;
import org.junit.Before;
@ -31,6 +30,7 @@ import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
@ -99,28 +99,28 @@ public class RequestParamMethodArgumentResolverTests {
String.class, MultipartFile.class, List.class, Part.class,
MultipartFile.class, String.class, String.class, Optional.class);
paramNamedDefaultValueString = new MethodParameter(method, 0);
paramNamedStringArray = new MethodParameter(method, 1);
paramNamedMap = new MethodParameter(method, 2);
paramMultipartFile = new MethodParameter(method, 3);
paramMultipartFileList = new MethodParameter(method, 4);
paramMultipartFileArray = new MethodParameter(method, 5);
paramPart = new MethodParameter(method, 6);
paramPartList = new MethodParameter(method, 7);
paramPartArray = new MethodParameter(method, 8);
paramMap = new MethodParameter(method, 9);
paramStringNotAnnot = new MethodParameter(method, 10);
paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0);
paramNamedStringArray = new SynthesizingMethodParameter(method, 1);
paramNamedMap = new SynthesizingMethodParameter(method, 2);
paramMultipartFile = new SynthesizingMethodParameter(method, 3);
paramMultipartFileList = new SynthesizingMethodParameter(method, 4);
paramMultipartFileArray = new SynthesizingMethodParameter(method, 5);
paramPart = new SynthesizingMethodParameter(method, 6);
paramPartList = new SynthesizingMethodParameter(method, 7);
paramPartArray = new SynthesizingMethodParameter(method, 8);
paramMap = new SynthesizingMethodParameter(method, 9);
paramStringNotAnnot = new SynthesizingMethodParameter(method, 10);
paramStringNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramMultipartFileNotAnnot = new MethodParameter(method, 11);
paramMultipartFileNotAnnot = new SynthesizingMethodParameter(method, 11);
paramMultipartFileNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramMultipartFileListNotAnnot = new MethodParameter(method, 12);
paramMultipartFileListNotAnnot = new SynthesizingMethodParameter(method, 12);
paramMultipartFileListNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramPartNotAnnot = new MethodParameter(method, 13);
paramPartNotAnnot = new SynthesizingMethodParameter(method, 13);
paramPartNotAnnot.initParameterNameDiscovery(paramNameDiscoverer);
paramRequestPartAnnot = new MethodParameter(method, 14);
paramRequired = new MethodParameter(method, 15);
paramNotRequired = new MethodParameter(method, 16);
paramOptional = new MethodParameter(method, 17);
paramRequestPartAnnot = new SynthesizingMethodParameter(method, 14);
paramRequired = new SynthesizingMethodParameter(method, 15);
paramNotRequired = new SynthesizingMethodParameter(method, 16);
paramOptional = new SynthesizingMethodParameter(method, 17);
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -49,6 +49,7 @@ import org.springframework.core.ExceptionDepthComparator;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.ui.Model;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@ -233,7 +234,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
Object[] args = new Object[paramTypes.length];
Class<?> handlerType = handler.getClass();
for (int i = 0; i < args.length; i++) {
MethodParameter methodParam = new MethodParameter(handlerMethod, i);
MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i);
GenericTypeResolver.resolveParameterType(methodParam, handlerType);
Class<?> paramType = methodParam.getParameterType();
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -44,6 +44,7 @@ import org.springframework.core.ExceptionDepthComparator;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.HttpStatus;
@ -258,7 +259,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
Object[] args = new Object[paramTypes.length];
Class<?> handlerType = handler.getClass();
for (int i = 0; i < args.length; i++) {
MethodParameter methodParam = new MethodParameter(handlerMethod, i);
MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i);
GenericTypeResolver.resolveParameterType(methodParam, handlerType);
Class<?> paramType = methodParam.getParameterType();
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException);

View File

@ -41,6 +41,7 @@ import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.objenesis.ObjenesisException;
import org.springframework.objenesis.SpringObjenesis;
import org.springframework.util.AntPathMatcher;
@ -486,7 +487,7 @@ public class MvcUriComponentsBuilder {
final Map<String, Object> uriVars = new HashMap<String, Object>();
for (int i = 0; i < paramCount; i++) {
MethodParameter param = new MethodParameter(method, i);
MethodParameter param = new SynthesizingMethodParameter(method, i);
param.initParameterNameDiscovery(parameterNameDiscoverer);
contributor.contributeMethodArgument(param, args[i], builder, uriVars);
}

View File

@ -75,7 +75,6 @@ import org.springframework.web.util.WebUtils;
*/
public class RequestPartMethodArgumentResolver extends AbstractMessageConverterMethodArgumentResolver {
/**
* Basic constructor with converters only.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -26,6 +26,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.util.LinkedMultiValueMap;
@ -66,11 +67,11 @@ public class MatrixVariablesMapMethodArgumentResolverTests {
Method method = getClass().getMethod("handle", String.class,
Map.class, MultiValueMap.class, MultiValueMap.class, Map.class);
this.paramString = new MethodParameter(method, 0);
this.paramMap = new MethodParameter(method, 1);
this.paramMultivalueMap = new MethodParameter(method, 2);
this.paramMapForPathVar = new MethodParameter(method, 3);
this.paramMapWithName = new MethodParameter(method, 4);
this.paramString = new SynthesizingMethodParameter(method, 0);
this.paramMap = new SynthesizingMethodParameter(method, 1);
this.paramMultivalueMap = new SynthesizingMethodParameter(method, 2);
this.paramMapForPathVar = new SynthesizingMethodParameter(method, 3);
this.paramMapWithName = new SynthesizingMethodParameter(method, 4);
this.mavContainer = new ModelAndViewContainer();
this.request = new MockHttpServletRequest();
@ -91,7 +92,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests {
@Test
public void resolveArgument() throws Exception {
MultiValueMap<String, String> params = getMatrixVariables("cars");
params.add("colors", "red");
params.add("colors", "green");
@ -113,7 +113,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests {
@Test
public void resolveArgumentPathVariable() throws Exception {
MultiValueMap<String, String> params1 = getMatrixVariables("cars");
params1.add("colors", "red");
params1.add("colors", "purple");
@ -137,7 +136,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests {
@Test
public void resolveArgumentNoParams() throws Exception {
@SuppressWarnings("unchecked")
Map<String, String> map = (Map<String, String>) this.resolver.resolveArgument(
this.paramMap, this.mavContainer, this.webRequest, null);
@ -147,7 +145,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests {
@Test
public void resolveArgumentNoMatch() throws Exception {
MultiValueMap<String, String> params2 = getMatrixVariables("planes");
params2.add("colors", "yellow");
params2.add("colors", "orange");
@ -162,7 +159,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests {
@SuppressWarnings("unchecked")
private MultiValueMap<String, String> getMatrixVariables(String pathVarName) {
Map<String, MultiValueMap<String, String>> matrixVariables =
(Map<String, MultiValueMap<String, String>>) this.request.getAttribute(
HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE);
@ -182,4 +178,4 @@ public class MatrixVariablesMapMethodArgumentResolverTests {
@MatrixVariable("name") Map<String, String> mapWithName) {
}
}
}

View File

@ -16,16 +16,12 @@
package org.springframework.web.servlet.mvc.method.annotation;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.servlet.http.Part;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@ -36,6 +32,7 @@ import org.junit.Test;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
@ -58,6 +55,9 @@ import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.multipart.support.RequestPartServletServerHttpRequest;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
/**
* Test fixture with {@link RequestPartMethodArgumentResolver} and mock {@link HttpMessageConverter}.
*
@ -102,26 +102,26 @@ public class RequestPartMethodArgumentResolverTests {
Integer.TYPE, MultipartFile.class, Part.class, List.class, Part[].class,
MultipartFile.class, Optional.class, Optional.class, Optional.class);
paramRequestPart = new MethodParameter(method, 0);
paramRequestPart = new SynthesizingMethodParameter(method, 0);
paramRequestPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
paramNamedRequestPart = new MethodParameter(method, 1);
paramValidRequestPart = new MethodParameter(method, 2);
paramMultipartFile = new MethodParameter(method, 3);
paramMultipartFileList = new MethodParameter(method, 4);
paramMultipartFileArray = new MethodParameter(method, 5);
paramInt = new MethodParameter(method, 6);
paramMultipartFileNotAnnot = new MethodParameter(method, 7);
paramNamedRequestPart = new SynthesizingMethodParameter(method, 1);
paramValidRequestPart = new SynthesizingMethodParameter(method, 2);
paramMultipartFile = new SynthesizingMethodParameter(method, 3);
paramMultipartFileList = new SynthesizingMethodParameter(method, 4);
paramMultipartFileArray = new SynthesizingMethodParameter(method, 5);
paramInt = new SynthesizingMethodParameter(method, 6);
paramMultipartFileNotAnnot = new SynthesizingMethodParameter(method, 7);
paramMultipartFileNotAnnot.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
paramPart = new MethodParameter(method, 8);
paramPart = new SynthesizingMethodParameter(method, 8);
paramPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
paramPartList = new MethodParameter(method, 9);
paramPartArray = new MethodParameter(method, 10);
paramRequestParamAnnot = new MethodParameter(method, 11);
optionalMultipartFile = new MethodParameter(method, 12);
paramPartList = new SynthesizingMethodParameter(method, 9);
paramPartArray = new SynthesizingMethodParameter(method, 10);
paramRequestParamAnnot = new SynthesizingMethodParameter(method, 11);
optionalMultipartFile = new SynthesizingMethodParameter(method, 12);
optionalMultipartFile.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
optionalPart = new MethodParameter(method, 13);
optionalPart = new SynthesizingMethodParameter(method, 13);
optionalPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
optionalRequestPart = new MethodParameter(method, 14);
optionalRequestPart = new SynthesizingMethodParameter(method, 14);
messageConverter = mock(HttpMessageConverter.class);
given(messageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -23,6 +23,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.web.bind.annotation.CookieValue;
@ -48,18 +49,20 @@ public class ServletCookieValueMethodArgumentResolverTests {
private MockHttpServletRequest request;
@Before
public void setUp() throws Exception {
resolver = new ServletCookieValueMethodArgumentResolver(null);
Method method = getClass().getMethod("params", Cookie.class, String.class);
cookieParameter = new MethodParameter(method, 0);
cookieStringParameter = new MethodParameter(method, 1);
cookieParameter = new SynthesizingMethodParameter(method, 0);
cookieStringParameter = new SynthesizingMethodParameter(method, 1);
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
}
@Test
public void resolveCookieArgument() throws Exception {
Cookie expected = new Cookie("name", "foo");
@ -78,8 +81,9 @@ public class ServletCookieValueMethodArgumentResolverTests {
assertEquals("Invalid result", cookie.getValue(), result);
}
public void params(@CookieValue("name") Cookie cookie,
@CookieValue(name = "name", defaultValue = "bar") String cookieString) {
}
}
}