diff --git a/spring-web/src/test/java/org/springframework/web/method/ResolvableMethod.java b/spring-web/src/test/java/org/springframework/web/method/ResolvableMethod.java index c0daebb69c..ff627df1ab 100644 --- a/spring-web/src/test/java/org/springframework/web/method/ResolvableMethod.java +++ b/spring-web/src/test/java/org/springframework/web/method/ResolvableMethod.java @@ -47,6 +47,7 @@ import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.SynthesizingMethodParameter; +import org.springframework.lang.Nullable; import org.springframework.objenesis.ObjenesisException; import org.springframework.objenesis.SpringObjenesis; import org.springframework.util.Assert; @@ -120,6 +121,7 @@ import static java.util.stream.Collectors.*; * * * @author Rossen Stoyanchev + * @since 5.0 */ public class ResolvableMethod { @@ -133,7 +135,7 @@ public class ResolvableMethod { private ResolvableMethod(Method method) { - Assert.notNull(method, "method is required"); + Assert.notNull(method, "Method is required"); this.method = method; } @@ -202,14 +204,14 @@ public class ResolvableMethod { return new ArgResolver().annotNotPresent(annotationTypes); } - @Override public String toString() { return "ResolvableMethod=" + formatMethod(); } + private String formatMethod() { - return (this.method().getName() + + return (method().getName() + Arrays.stream(this.method.getParameters()) .map(this::formatParameter) .collect(joining(",\n\t", "(\n\t", "\n)"))); @@ -246,7 +248,7 @@ public class ResolvableMethod { /** - * Main entry point providing access to a {@code ResolvableMethod} builder. + * Create a {@code ResolvableMethod} builder for the given handler class. */ public static Builder on(Class objectClass) { return new Builder<>(objectClass); @@ -262,13 +264,11 @@ public class ResolvableMethod { private final List> filters = new ArrayList<>(4); - private Builder(Class objectClass) { Assert.notNull(objectClass, "Class must not be null"); this.objectClass = objectClass; } - private void addFilter(String message, Predicate filter) { this.filters.add(new LabeledPredicate<>(message, filter)); } @@ -277,7 +277,7 @@ public class ResolvableMethod { * Filter on methods with the given name. */ public Builder named(String methodName) { - addFilter("methodName=" + methodName, m -> m.getName().equals(methodName)); + addFilter("methodName=" + methodName, method -> method.getName().equals(methodName)); return this; } @@ -384,7 +384,6 @@ public class ResolvableMethod { return new ResolvableMethod(method); } - // Build & resolve shortcuts... /** @@ -438,7 +437,6 @@ public class ResolvableMethod { return returning(returnType).build().returnType(); } - @Override public String toString() { return "ResolvableMethod.Builder[\n" + @@ -452,6 +450,7 @@ public class ResolvableMethod { } } + /** * Predicate with a descriptive label. */ @@ -461,7 +460,6 @@ public class ResolvableMethod { private final Predicate delegate; - private LabeledPredicate(String label, Predicate delegate) { this.label = label; this.delegate = delegate; @@ -494,6 +492,7 @@ public class ResolvableMethod { } } + /** * Resolver for method arguments. */ @@ -501,7 +500,6 @@ public class ResolvableMethod { private final List> filters = new ArrayList<>(4); - @SafeVarargs private ArgResolver(Predicate... filter) { this.filters.addAll(Arrays.asList(filter)); @@ -593,17 +591,18 @@ public class ResolvableMethod { } } + private static class MethodInvocationInterceptor implements org.springframework.cglib.proxy.MethodInterceptor, MethodInterceptor { private Method invokedMethod; - Method getInvokedMethod() { return this.invokedMethod; } @Override + @Nullable public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) { if (ReflectionUtils.isObjectMethod(method)) { return ReflectionUtils.invokeMethod(method, object, args); @@ -615,6 +614,7 @@ public class ResolvableMethod { } @Override + @Nullable public Object invoke(org.aopalliance.intercept.MethodInvocation inv) throws Throwable { return intercept(inv.getThis(), inv.getMethod(), inv.getArguments(), null); } diff --git a/src/docs/asciidoc/core/core-aop.adoc b/src/docs/asciidoc/core/core-aop.adoc index 2d3eae9ceb..a2c47423c8 100644 --- a/src/docs/asciidoc/core/core-aop.adoc +++ b/src/docs/asciidoc/core/core-aop.adoc @@ -2890,13 +2890,13 @@ container and once through the aspect. [[aop-configurable-testing]] ==== Unit testing @Configurable objects -One of the goals of the `@Configurable` support is to enable independent unit testing of -domain objects without the difficulties associated with hard-coded lookups. If -`@Configurable` types have not been woven by AspectJ then the annotation has no affect +One of the goals of the `@Configurable` support is to enable independent unit testing +of domain objects without the difficulties associated with hard-coded lookups. +If `@Configurable` types have not been woven by AspectJ, the annotation has no affect during unit testing, and you can simply set mock or stub property references in the object under test and proceed as normal. If `@Configurable` types __have__ been woven by AspectJ then you can still unit test outside of the container as normal, but you will -see a warning message each time that you construct an `@Configurable` object indicating +see a warning message each time that you construct a `@Configurable` object indicating that it has not been configured by Spring. diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc index 0615b47749..6a3c4c8a35 100644 --- a/src/docs/asciidoc/web/webmvc.adoc +++ b/src/docs/asciidoc/web/webmvc.adoc @@ -547,7 +547,7 @@ The table below lists the available `HandlerExceptionResolver` implementations: codes based on the value in the annotation. | `ExceptionHandlerExceptionResolver` -| Resolves exceptions by invoking an `@ExceptionHandler` method in an `@Controller` or an +| Resolves exceptions by invoking an `@ExceptionHandler` method in an `@Controller` or a `@ControllerAdvice` class. See <>. |=== @@ -2660,7 +2660,7 @@ to the model: ===== Jackson JSONP In order to enable http://en.wikipedia.org/wiki/JSONP[JSONP] support for `@ResponseBody` -and `ResponseEntity` methods, declare an `@ControllerAdvice` bean that extends +and `ResponseEntity` methods, declare a `@ControllerAdvice` bean that extends `AbstractJsonpResponseBodyAdvice` as shown below where the constructor argument indicates the JSONP query parameter name(s):