diff --git a/spring-core/src/main/java/org/springframework/core/MethodParameter.java b/spring-core/src/main/java/org/springframework/core/MethodParameter.java index 6a0137aa57..19c397e627 100644 --- a/spring-core/src/main/java/org/springframework/core/MethodParameter.java +++ b/spring-core/src/main/java/org/springframework/core/MethodParameter.java @@ -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. * + *
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 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 adaptAnnotation(A annotation) {
+ return annotation;
+ }
+
+ /**
+ * A template method to post-process a given annotation array before
+ * returning it to the caller.
+ * 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) {
diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java
index 8432d75569..d52cfa5498 100644
--- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java
+++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java
@@ -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);
}
diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
index 030fc45268..b42818a03d 100644
--- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
+++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
@@ -266,6 +266,7 @@ public abstract class AnnotationUtils {
@Deprecated
public static Set getRepeatableAnnotation(Method method,
Class extends Annotation> containerAnnotationType, Class annotationType) {
+
return getRepeatableAnnotations(method, annotationType, containerAnnotationType);
}
@@ -280,6 +281,7 @@ public abstract class AnnotationUtils {
@Deprecated
public static Set getRepeatableAnnotation(AnnotatedElement annotatedElement,
Class extends Annotation> containerAnnotationType, Class annotationType) {
+
return getRepeatableAnnotations(annotatedElement, annotationType, containerAnnotationType);
}
@@ -311,6 +313,7 @@ public abstract class AnnotationUtils {
*/
public static Set getRepeatableAnnotations(AnnotatedElement annotatedElement,
Class 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}.
* Meta-annotations will be searched if the annotation is not
* present 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.
- *
* This method provides fully recursive annotation reading capabilities on par with
* the reflection-based {@link org.springframework.core.type.StandardAnnotationMetadata}.
- *
* NOTE: 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.
*
- *
* @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
* attribute alias 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
* synthesizable; {@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
* attribute alias 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) annotationType, SynthesizedAnnotation.class }, handler);
+ A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(),
+ new Class>[] {(Class) annotationType, SynthesizedAnnotation.class}, handler);
return synthesizedAnnotation;
}
@@ -1250,7 +1246,6 @@ public abstract class AnnotationUtils {
* 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 synthesizeAnnotation(Map 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.
- *
* 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 {
* synthesizable (i.e., in need of being wrapped in a dynamic
* proxy that provides functionality above that of a standard JDK
* annotation).
- *
* Specifically, an annotation is synthesizable if it declares
* any attributes that are configured as aliased pairs via
* {@link AliasFor @AliasFor} or if any nested annotations used by the
* annotation declare such aliased pairs.
- *
* @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}.
- *
* 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 attributes.
- *
* 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 Specifically, this method enforces attribute alias 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 annotationType;
private final Class extends Annotation> containerAnnotationType;
@@ -1809,17 +1782,13 @@ public abstract class AnnotationUtils {
private final Set result = new LinkedHashSet();
-
AnnotationCollector(Class 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;
}
diff --git a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizingMethodParameter.java b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizingMethodParameter.java
new file mode 100644
index 0000000000..af26f0a345
--- /dev/null
+++ b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizingMethodParameter.java
@@ -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 adaptAnnotation(A annotation) {
+ return AnnotationUtils.synthesizeAnnotation(annotation, getAnnotatedElement());
+ }
+
+ @Override
+ protected Annotation[] adaptAnnotationArray(Annotation[] annotations) {
+ return AnnotationUtils.synthesizeAnnotationArray(annotations, getAnnotatedElement());
+ }
+
+}
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java
index 33538c2976..b7898d3ef4 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java
@@ -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);
diff --git a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java
index 6985c9eb48..429b5ce8ac 100644
--- a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java
+++ b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java
@@ -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));
diff --git a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java
index 2c40b6b465..ffc0954109 100644
--- a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java
+++ b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java
@@ -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(
diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java
index eec2255405..78a2bb02be 100644
--- a/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java
+++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java
@@ -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);
}
diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java
index ff66d18c9b..eb8693338c 100644
--- a/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java
+++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java
@@ -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;
diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
index 6905dce959..5be84c0077 100644
--- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
+++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
@@ -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);
diff --git a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java
index c209c52c06..3ef1b4fea8 100644
--- a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java
+++ b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java
@@ -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
diff --git a/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java b/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java
index f061d86ed2..1df794a7c5 100644
--- a/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java
+++ b/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java
@@ -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