diff --git a/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java index 5dd0fb33aa..b29f1cd9c8 100644 --- a/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 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. @@ -19,6 +19,7 @@ package org.springframework.beans.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -62,7 +63,8 @@ public abstract class AnnotationBeanUtils { public static void copyPropertiesToBean(Annotation ann, Object bean, @Nullable StringValueResolver valueResolver, String... excludedProperties) { - Set excluded = new HashSet<>(Arrays.asList(excludedProperties)); + Set excluded = (excludedProperties.length == 0 ? Collections.emptySet() : + new HashSet<>(Arrays.asList(excludedProperties))); Method[] annotationProperties = ann.annotationType().getDeclaredMethods(); BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(bean); for (Method annotationProperty : annotationProperties) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java index 8044db78d4..888f33186d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java @@ -276,7 +276,7 @@ abstract class AutowireUtils { /** - * Reflective InvocationHandler for lazy access to the current target object. + * Reflective {@link InvocationHandler} for lazy access to the current target object. */ @SuppressWarnings("serial") private static class ObjectFactoryDelegatingInvocationHandler implements InvocationHandler, Serializable { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/AutowireUtilsTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/AutowireUtilsTests.java index 1dc7338142..48cf786160 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/AutowireUtilsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/support/AutowireUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -27,6 +27,8 @@ import org.springframework.util.ReflectionUtils; import static org.junit.Assert.*; /** + * Unit tests for {@link AutowireUtils}. + * * @author Juergen Hoeller * @author Sam Brannen */ @@ -36,7 +38,7 @@ public class AutowireUtilsTests { public void genericMethodReturnTypes() { Method notParameterized = ReflectionUtils.findMethod(MyTypeWithMethods.class, "notParameterized"); assertEquals(String.class, - AutowireUtils.resolveReturnTypeForFactoryMethod(notParameterized, new Object[]{}, getClass().getClassLoader())); + AutowireUtils.resolveReturnTypeForFactoryMethod(notParameterized, new Object[0], getClass().getClassLoader())); Method notParameterizedWithArguments = ReflectionUtils.findMethod(MyTypeWithMethods.class, "notParameterizedWithArguments", Integer.class, Boolean.class); assertEquals(String.class, 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 4412b6770c..d98261cafa 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -56,14 +56,14 @@ import org.springframework.util.StringUtils; *

Note that most of the features of this class are not provided by the * JDK's introspection facilities themselves. * - *

As a general rule for runtime-retained annotations (e.g. for transaction - * control, authorization, or service exposure), always use the lookup methods - * on this class (e.g., {@link #findAnnotation(Method, Class)}, - * {@link #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)}) - * instead of the plain annotation lookup methods in the JDK. You can still - * explicitly choose between a get lookup on the given class level only - * ({@link #getAnnotation(Method, Class)}) and a find lookup in the entire - * inheritance hierarchy of the given method ({@link #findAnnotation(Method, Class)}). + *

As a general rule for runtime-retained application annotations (e.g. for + * transaction control, authorization, or service exposure), always use the + * lookup methods on this class (e.g. {@link #findAnnotation(Method, Class)} or + * {@link #getAnnotation(Method, Class)}) instead of the plain annotation lookup + * methods in the JDK. You can still explicitly choose between a get + * lookup on the given class level only ({@link #getAnnotation(Method, Class)}) + * and a find lookup in the entire inheritance hierarchy of the given + * method ({@link #findAnnotation(Method, Class)}). * *

Terminology

* The terms directly present, indirectly present, and @@ -476,7 +476,13 @@ public abstract class AnnotationUtils { * @since 4.2 */ @Nullable - public static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType) { + public static A findAnnotation( + AnnotatedElement annotatedElement, @Nullable Class annotationType) { + + if (annotationType == null) { + return null; + } + // Do NOT store result in the findAnnotationCache since doing so could break // findAnnotation(Class, Class) and findAnnotation(Method, Class). A ann = findAnnotation(annotatedElement, annotationType, new HashSet<>()); @@ -707,7 +713,7 @@ public abstract class AnnotationUtils { * @return the first matching annotation, or {@code null} if not found */ @Nullable - public static A findAnnotation(Class clazz, Class annotationType) { + public static A findAnnotation(Class clazz, @Nullable Class annotationType) { return findAnnotation(clazz, annotationType, true); } @@ -803,8 +809,8 @@ public abstract class AnnotationUtils { * @param annotationType the annotation type to look for * @param clazz the class to check for the annotation on (may be {@code null}) * @return the first {@link Class} in the inheritance hierarchy that - * declares an annotation of the specified {@code annotationType}, or - * {@code null} if not found + * declares an annotation of the specified {@code annotationType}, + * or {@code null} if not found * @see Class#isAnnotationPresent(Class) * @see Class#getDeclaredAnnotations() * @see #findAnnotationDeclaringClassForTypes(List, Class) @@ -835,7 +841,7 @@ public abstract class AnnotationUtils { * one of several candidate {@linkplain Annotation annotations}, so we * need to handle this explicitly. * @param annotationTypes the annotation types to look for - * @param clazz the class to check for the annotations on, or {@code null} + * @param clazz the class to check for the annotation on (may be {@code null}) * @return the first {@link Class} in the inheritance hierarchy that * declares an annotation of at least one of the specified * {@code annotationTypes}, or {@code null} if not found @@ -1031,7 +1037,9 @@ public abstract class AnnotationUtils { * corresponding attribute values as values (never {@code null}) * @see #getAnnotationAttributes(Annotation, boolean, boolean) */ - public static Map getAnnotationAttributes(Annotation annotation, boolean classValuesAsString) { + public static Map getAnnotationAttributes( + Annotation annotation, boolean classValuesAsString) { + return getAnnotationAttributes(annotation, classValuesAsString, false); } @@ -1051,8 +1059,8 @@ public abstract class AnnotationUtils { * and corresponding attribute values as values (never {@code null}) * @since 3.1.1 */ - public static AnnotationAttributes getAnnotationAttributes(Annotation annotation, boolean classValuesAsString, - boolean nestedAnnotationsAsMap) { + public static AnnotationAttributes getAnnotationAttributes( + Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) { return getAnnotationAttributes(null, annotation, classValuesAsString, nestedAnnotationsAsMap); } @@ -1070,7 +1078,9 @@ public abstract class AnnotationUtils { * @since 4.2 * @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean) */ - public static AnnotationAttributes getAnnotationAttributes(@Nullable AnnotatedElement annotatedElement, Annotation annotation) { + public static AnnotationAttributes getAnnotationAttributes( + @Nullable AnnotatedElement annotatedElement, Annotation annotation) { + return getAnnotationAttributes(annotatedElement, annotation, false, false); } @@ -1448,10 +1458,7 @@ public abstract class AnnotationUtils { */ @Nullable public static Object getDefaultValue(@Nullable Annotation annotation, @Nullable String attributeName) { - if (annotation == null) { - return null; - } - return getDefaultValue(annotation.annotationType(), attributeName); + return (annotation != null ? getDefaultValue(annotation.annotationType(), attributeName) : null); } /** diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java index 2df02f1c64..0fb819d178 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 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. @@ -42,11 +42,11 @@ import org.springframework.util.StringUtils; */ public abstract class AbstractServerHttpRequest implements ServerHttpRequest { - private static final Log logger = LogFactory.getLog(ServerHttpRequest.class); - private static final Pattern QUERY_PATTERN = Pattern.compile("([^&=]+)(=?)([^&]+)?"); + private static final Log logger = LogFactory.getLog(ServerHttpRequest.class); + private final URI uri; private final RequestPath path; diff --git a/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java b/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java index 465c3e5f4b..2277edfff3 100644 --- a/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java +++ b/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 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. @@ -66,8 +66,9 @@ class HtmlCharacterEntityDecoder { this.originalMessage.indexOf('&', this.nextPotentialReferencePosition); if (this.nextSemicolonPosition != -1 && - this.nextSemicolonPosition < this.nextPotentialReferencePosition) + this.nextSemicolonPosition < this.nextPotentialReferencePosition) { this.nextSemicolonPosition = this.originalMessage.indexOf(';', this.nextPotentialReferencePosition + 1); + } boolean isPotentialReference = (this.nextPotentialReferencePosition != -1 && this.nextSemicolonPosition != -1 && @@ -94,12 +95,13 @@ class HtmlCharacterEntityDecoder { int skipUntilIndex = (this.nextPotentialReferencePosition != -1 ? this.nextPotentialReferencePosition : this.originalMessage.length()); if (skipUntilIndex - this.currentPosition > 3) { - this.decodedMessage.append(this.originalMessage.substring(this.currentPosition, skipUntilIndex)); + this.decodedMessage.append(this.originalMessage, this.currentPosition, skipUntilIndex); this.currentPosition = skipUntilIndex; } else { - while (this.currentPosition < skipUntilIndex) + while (this.currentPosition < skipUntilIndex) { this.decodedMessage.append(this.originalMessage.charAt(this.currentPosition++)); + } } } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java index 8143dd3119..e781d7298a 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -419,7 +419,7 @@ public abstract class ResponseEntityExceptionHandler { } /** - * Customize the response for NoHandlerFoundException. + * Customize the response for AsyncRequestTimeoutException. *

This method delegates to {@link #handleExceptionInternal}. * @param ex the exception * @param headers the headers to be written to the response @@ -448,7 +448,7 @@ public abstract class ResponseEntityExceptionHandler { } /** - * A single place to customize the response body of all Exception types. + * A single place to customize the response body of all exception types. *

The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE} * request attribute and creates a {@link ResponseEntity} from the given * body, headers, and status. diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc index 67e22103ae..68e8875a1b 100644 --- a/src/docs/asciidoc/web/webmvc.adoc +++ b/src/docs/asciidoc/web/webmvc.adoc @@ -1354,7 +1354,7 @@ The default mapping pattern `/{asterisk}{asterisk}` is excluded from scoring and sorted last. Also prefix patterns such as `/public/{asterisk}{asterisk}` are considered less specific than other pattern that don't have double wildcards. -For the full details see `AntPatternComparator` in `AntPathMatcher` and also keep mind that +For the full details see `AntPatternComparator` in `AntPathMatcher` and also keep in mind that the `PathMatcher` implementation used can be customized. See <> in the configuration section.