Relaxed final declarations and protected doInvoke methods

Issue: SPR-12484
This commit is contained in:
Juergen Hoeller 2014-12-01 15:07:24 +01:00
parent efb114d49a
commit 2496d68e9f
3 changed files with 46 additions and 38 deletions

View File

@ -29,13 +29,14 @@ import org.springframework.messaging.handler.HandlerMethod;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* Invokes the handler method for a given message after resolving * Invokes the handler method for a given message after resolving its method argument
* its method argument values through registered {@link HandlerMethodArgumentResolver}s. * values through registered {@link HandlerMethodArgumentResolver}s.
* *
* <p>Use {@link #setMessageMethodArgumentResolvers(HandlerMethodArgumentResolver)} * <p>Use {@link #setMessageMethodArgumentResolvers(HandlerMethodArgumentResolver)}
* to customize the list of argument resolvers. * to customize the list of argument resolvers.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 4.0 * @since 4.0
*/ */
public class InvocableHandlerMethod extends HandlerMethod { public class InvocableHandlerMethod extends HandlerMethod {
@ -66,7 +67,9 @@ public class InvocableHandlerMethod extends HandlerMethod {
* @param parameterTypes the method parameter types * @param parameterTypes the method parameter types
* @throws NoSuchMethodException when the method cannot be found * @throws NoSuchMethodException when the method cannot be found
*/ */
public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException { public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
throws NoSuchMethodException {
super(bean, methodName, parameterTypes); super(bean, methodName, parameterTypes);
} }
@ -93,12 +96,12 @@ public class InvocableHandlerMethod extends HandlerMethod {
* @throws Exception raised if no suitable argument resolver can be found, * @throws Exception raised if no suitable argument resolver can be found,
* or the method raised an exception * or the method raised an exception
*/ */
public final Object invoke(Message<?> message, Object... providedArgs) throws Exception { public Object invoke(Message<?> message, Object... providedArgs) throws Exception {
Object[] args = getMethodArgumentValues(message, providedArgs); Object[] args = getMethodArgumentValues(message, providedArgs);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Resolved arguments: " + Arrays.asList(args)); logger.trace("Resolved arguments: " + Arrays.asList(args));
} }
Object returnValue = invoke(args); Object returnValue = doInvoke(args);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Returned value: " + returnValue); logger.trace("Returned value: " + returnValue);
} }
@ -172,10 +175,11 @@ public class InvocableHandlerMethod extends HandlerMethod {
return null; return null;
} }
/** /**
* Invoke the handler method with the given argument values. * Invoke the handler method with the given argument values.
*/ */
private Object invoke(Object... args) throws Exception { protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod()); ReflectionUtils.makeAccessible(getBridgedMethod());
try { try {
return getBridgedMethod().invoke(getBean(), args); return getBridgedMethod().invoke(getBean(), args);

View File

@ -32,17 +32,18 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
/** /**
* Provides a method for invoking the handler method for a given request after resolving its method argument * Provides a method for invoking the handler method for a given request after resolving its
* values through registered {@link HandlerMethodArgumentResolver}s. * method argument values through registered {@link HandlerMethodArgumentResolver}s.
* *
* <p>Argument resolution often requires a {@link WebDataBinder} for data binding or for type conversion. * <p>Argument resolution often requires a {@link WebDataBinder} for data binding or for type
* Use the {@link #setDataBinderFactory(WebDataBinderFactory)} property to supply a binder factory to pass to * conversion. Use the {@link #setDataBinderFactory(WebDataBinderFactory)} property to supply
* argument resolvers. * a binder factory to pass to argument resolvers.
* *
* <p>Use {@link #setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite)} to customize * <p>Use {@link #setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite)}
* the list of argument resolvers. * to customize the list of argument resolvers.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 3.1 * @since 3.1
*/ */
public class InvocableHandlerMethod extends HandlerMethod { public class InvocableHandlerMethod extends HandlerMethod {
@ -75,7 +76,9 @@ public class InvocableHandlerMethod extends HandlerMethod {
* @param parameterTypes the method parameter types * @param parameterTypes the method parameter types
* @throws NoSuchMethodException when the method cannot be found * @throws NoSuchMethodException when the method cannot be found
*/ */
public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException { public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
throws NoSuchMethodException {
super(bean, methodName, parameterTypes); super(bean, methodName, parameterTypes);
} }
@ -107,18 +110,20 @@ public class InvocableHandlerMethod extends HandlerMethod {
/** /**
* Invoke the method after resolving its argument values in the context of the given request. <p>Argument * Invoke the method after resolving its argument values in the context of the given request.
* values are commonly resolved through {@link HandlerMethodArgumentResolver}s. The {@code provideArgs} * <p>Argument values are commonly resolved through {@link HandlerMethodArgumentResolver}s.
* parameter however may supply argument values to be used directly, i.e. without argument resolution. * The {@code provideArgs} parameter however may supply argument values to be used directly,
* Examples of provided argument values include a {@link WebDataBinder}, a {@link SessionStatus}, or * i.e. without argument resolution. Examples of provided argument values include a
* a thrown exception instance. Provided argument values are checked before argument resolvers. * {@link WebDataBinder}, a {@link SessionStatus}, or a thrown exception instance.
* Provided argument values are checked before argument resolvers.
* @param request the current request * @param request the current request
* @param mavContainer the ModelAndViewContainer for this request * @param mavContainer the ModelAndViewContainer for this request
* @param providedArgs "given" arguments matched by type, not resolved * @param providedArgs "given" arguments matched by type, not resolved
* @return the raw value returned by the invoked method * @return the raw value returned by the invoked method
* @exception Exception raised if no suitable argument resolver can be found, or the method raised an exception * @exception Exception raised if no suitable argument resolver can be found,
* or if the method raised an exception
*/ */
public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception { Object... providedArgs) throws Exception {
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
@ -129,7 +134,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
sb.append(Arrays.asList(args)); sb.append(Arrays.asList(args));
logger.trace(sb.toString()); logger.trace(sb.toString());
} }
Object returnValue = invoke(args); Object returnValue = doInvoke(args);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]"); logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
} }
@ -206,10 +211,11 @@ public class InvocableHandlerMethod extends HandlerMethod {
return null; return null;
} }
/** /**
* Invoke the handler method with the given argument values. * Invoke the handler method with the given argument values.
*/ */
private Object invoke(Object... args) throws Exception { protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod()); ReflectionUtils.makeAccessible(getBridgedMethod());
try { try {
return getBridgedMethod().invoke(getBean(), args); return getBridgedMethod().invoke(getBean(), args);

View File

@ -88,6 +88,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
} }
} }
/** /**
* Register {@link HandlerMethodReturnValueHandler} instances to use to * Register {@link HandlerMethodReturnValueHandler} instances to use to
* handle return values. * handle return values.
@ -99,16 +100,14 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
/** /**
* Invokes the method and handles the return value through one of the * Invokes the method and handles the return value through one of the
* configured {@link HandlerMethodReturnValueHandler}s. * configured {@link HandlerMethodReturnValueHandler}s.
*
* @param webRequest the current request * @param webRequest the current request
* @param mavContainer the ModelAndViewContainer for this request * @param mavContainer the ModelAndViewContainer for this request
* @param providedArgs "given" arguments matched by type, not resolved * @param providedArgs "given" arguments matched by type (not resolved)
*/ */
public final void invokeAndHandle(ServletWebRequest webRequest, public void invokeAndHandle(ServletWebRequest webRequest,
ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest); setResponseStatus(webRequest);
if (returnValue == null) { if (returnValue == null) {
@ -123,9 +122,9 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
} }
mavContainer.setRequestHandled(false); mavContainer.setRequestHandled(false);
try { try {
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
} }
catch (Exception ex) { catch (Exception ex) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
@ -165,20 +164,20 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
* Does this method have the response status instruction? * Does this method have the response status instruction?
*/ */
private boolean hasResponseStatus() { private boolean hasResponseStatus() {
return this.responseStatus != null; return (this.responseStatus != null);
} }
private String getReturnValueHandlingErrorMessage(String message, Object returnValue) { private String getReturnValueHandlingErrorMessage(String message, Object returnValue) {
StringBuilder sb = new StringBuilder(message); StringBuilder sb = new StringBuilder(message);
if (returnValue != null) { if (returnValue != null) {
sb.append(" [type=" + returnValue.getClass().getName() + "] "); sb.append(" [type=").append(returnValue.getClass().getName()).append("]");
} }
sb.append("[value=" + returnValue + "]"); sb.append(" [value=").append(returnValue).append("]");
return getDetailedErrorMessage(sb.toString()); return getDetailedErrorMessage(sb.toString());
} }
/** /**
* Create a nested ServletInvocableHandlerMethod sub-class that returns the * Create a nested ServletInvocableHandlerMethod subclass that returns the
* the given value (or raises an Exception if the value is one) rather than * the given value (or raises an Exception if the value is one) rather than
* actually invoking the controller method. This is useful when processing * actually invoking the controller method. This is useful when processing
* async return values (e.g. Callable, DeferredResult, ListenableFuture). * async return values (e.g. Callable, DeferredResult, ListenableFuture).
@ -189,7 +188,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
/** /**
* A nested sub-class of {@code ServletInvocableHandlerMethod} that uses a * A nested subclass of {@code ServletInvocableHandlerMethod} that uses a
* simple {@link Callable} instead of the original controller as the handler in * simple {@link Callable} instead of the original controller as the handler in
* order to return the fixed (concurrent) result value given to it. Effectively * order to return the fixed (concurrent) result value given to it. Effectively
* "resumes" processing with the asynchronously produced return value. * "resumes" processing with the asynchronously produced return value.
@ -198,7 +197,6 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
private final MethodParameter returnType; private final MethodParameter returnType;
public ConcurrentResultHandlerMethod(final Object result, ConcurrentResultMethodParameter returnType) { public ConcurrentResultHandlerMethod(final Object result, ConcurrentResultMethodParameter returnType) {
super(new Callable<Object>() { super(new Callable<Object>() {
@Override @Override
@ -242,8 +240,9 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
} }
} }
/** /**
* MethodParameter sub-class based on the actual return value type or if * MethodParameter subclass based on the actual return value type or if
* that's null falling back on the generic type within the declared async * that's null falling back on the generic type within the declared async
* return type, e.g. Foo instead of {@code DeferredResult<Foo>}. * return type, e.g. Foo instead of {@code DeferredResult<Foo>}.
*/ */
@ -253,7 +252,6 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
private final ResolvableType returnType; private final ResolvableType returnType;
public ConcurrentResultMethodParameter(Object returnValue) { public ConcurrentResultMethodParameter(Object returnValue) {
super(-1); super(-1);
this.returnValue = returnValue; this.returnValue = returnValue;
@ -262,7 +260,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
@Override @Override
public Class<?> getParameterType() { public Class<?> getParameterType() {
return (returnValue != null ? returnValue.getClass() : this.returnType.getRawClass()); return (this.returnValue != null ? this.returnValue.getClass() : this.returnType.getRawClass());
} }
@Override @Override