Browse Source

Refactor SyncInvocableHandlerMethod

Switch from extension to delegation model, i.e. delegating to
InvocableHandlerMethod, so that only sync invocation is exposed and
only resolvers of type SyncHandlerMethodArgumentResolver are allowed
to be configured in a cleaner fashion.
pull/1357/head
Rossen Stoyanchev 8 years ago
parent
commit
5ae9afd5a5
  1. 7
      spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java
  2. 64
      spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SyncInvocableHandlerMethod.java
  3. 2
      spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java

7
spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java

@ -43,8 +43,9 @@ import org.springframework.web.reactive.HandlerResult; @@ -43,8 +43,9 @@ import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.server.ServerWebExchange;
/**
* A subclass of {@link HandlerMethod} that can resolve method arguments from
* a {@link ServerWebExchange} and use that to invoke the underlying method.
* Extension of {@link HandlerMethod} that invokes the underlying method with
* argument values resolved from the current HTTP request through a list of
* {@link HandlerMethodArgumentResolver}.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
@ -94,7 +95,7 @@ public class InvocableHandlerMethod extends HandlerMethod { @@ -94,7 +95,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
}
/**
* Return the conifgured argument resolvers.
* Return the configured argument resolvers.
*/
public List<HandlerMethodArgumentResolver> getResolvers() {
return this.resolvers;

64
spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SyncInvocableHandlerMethod.java

@ -19,69 +19,85 @@ package org.springframework.web.reactive.result.method; @@ -19,69 +19,85 @@ package org.springframework.web.reactive.result.method;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.util.Assert;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.server.ServerWebExchange;
/**
* Extension of {@code InvocableHandlerMethod} that can only be configured with
* synchronous argument resolvers and thus exposing an additional, synchronous
* {@link #invokeForHandlerResult} returning a {@code HandlerResult} vs
* {@code Mono<HandlerResult>}.
* Extension of {@link HandlerMethod} that invokes the underlying method via
* {@link InvocableHandlerMethod} but uses sync argument resolvers only and
* thus can return directly a {@link HandlerResult} with no async wrappers.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
public class SyncInvocableHandlerMethod extends InvocableHandlerMethod {
public class SyncInvocableHandlerMethod extends HandlerMethod {
private final InvocableHandlerMethod delegate;
public SyncInvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
this.delegate = new InvocableHandlerMethod(handlerMethod);
}
public SyncInvocableHandlerMethod(Object bean, Method method) {
super(bean, method);
this.delegate = new InvocableHandlerMethod(bean, method);
}
/**
* {@inheritDoc}
* <p>Resolvers must be of type {@link SyncHandlerMethodArgumentResolver}.
* @see #setSyncArgumentResolvers(List)
* Configure the argument resolvers to use to use for resolving method
* argument values against a {@code ServerWebExchange}.
*/
@Override
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.forEach(this::assertSyncResolvers);
super.setArgumentResolvers(resolvers);
public void setArgumentResolvers(List<SyncHandlerMethodArgumentResolver> resolvers) {
this.delegate.setArgumentResolvers(new ArrayList<>(resolvers));
}
private void assertSyncResolvers(HandlerMethodArgumentResolver resolver) {
Assert.isInstanceOf(SyncHandlerMethodArgumentResolver.class, resolver,
"SyncInvocableHandlerMethod requires resolvers of type " +
"SyncHandlerMethodArgumentResolver");
/**
* Return the configured argument resolvers.
*/
public List<SyncHandlerMethodArgumentResolver> getResolvers() {
return this.delegate.getResolvers().stream()
.map(resolver -> (SyncHandlerMethodArgumentResolver) resolver)
.collect(Collectors.toList());
}
/**
* Set the ParameterNameDiscoverer for resolving parameter names when needed
* (e.g. default request attribute name).
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer nameDiscoverer) {
this.delegate.setParameterNameDiscoverer(nameDiscoverer);
}
/**
* Convenient alternative to {@link #setArgumentResolvers(List)} to configure
* synchronous argument resolvers.
* Return the configured parameter name discoverer.
*/
public void setSyncArgumentResolvers(List<SyncHandlerMethodArgumentResolver> resolvers) {
setArgumentResolvers(new ArrayList<>(resolvers));
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.delegate.getParameterNameDiscoverer();
}
/**
* Delegate to the base class {@link #invoke} and also wait for the result.
* Since all argument resolvers are synchronous this won't actually block.
* Invoke the method for the given exchange.
* @param exchange the current exchange
* @param bindingContext the binding context to use
* @param providedArgs optional list of argument values to match by type
* @return Mono with a {@link HandlerResult}.
*/
public HandlerResult invokeForHandlerResult(ServerWebExchange exchange,
BindingContext bindingContext, Object... providedArgs) {
// This will not block with only sync resolvers allowed
return super.invoke(exchange, bindingContext, providedArgs).block();
return this.delegate.invoke(exchange, bindingContext, providedArgs).block();
}
}

2
spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.java

@ -409,7 +409,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application @@ -409,7 +409,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
private SyncInvocableHandlerMethod createBinderMethod(Object bean, Method method) {
SyncInvocableHandlerMethod invocable = new SyncInvocableHandlerMethod(bean, method);
invocable.setSyncArgumentResolvers(getInitBinderArgumentResolvers());
invocable.setArgumentResolvers(getInitBinderArgumentResolvers());
return invocable;
}

Loading…
Cancel
Save