Add ArgumentResolverConfigurer
Replace the List<HandlerMethodArgumentResolver> with a dedicated configurer that currently has one method accepting custom resolver registrations.
This commit is contained in:
parent
118f33aeda
commit
a8162c03f9
|
@ -26,7 +26,7 @@ import org.springframework.util.CollectionUtils;
|
|||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
||||
|
||||
/**
|
||||
* A subclass of {@code WebFluxConfigurationSupport} that detects and delegates
|
||||
|
@ -70,8 +70,8 @@ public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
this.configurers.addArgumentResolvers(resolvers);
|
||||
protected void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
||||
this.configurers.configureArgumentResolvers(configurer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.web.reactive.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -50,7 +49,7 @@ import org.springframework.web.reactive.accept.CompositeContentTypeResolver;
|
|||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
|
||||
import org.springframework.web.reactive.result.SimpleHandlerAdapter;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler;
|
||||
|
@ -240,11 +239,9 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
|
|||
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());
|
||||
adapter.setReactiveAdapterRegistry(webFluxAdapterRegistry());
|
||||
|
||||
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
|
||||
addArgumentResolvers(resolvers);
|
||||
if (!resolvers.isEmpty()) {
|
||||
adapter.setCustomArgumentResolvers(resolvers);
|
||||
}
|
||||
ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer();
|
||||
configureArgumentResolvers(configurer);
|
||||
adapter.setArgumentResolverConfigurer(configurer);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
@ -257,9 +254,9 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
|
|||
}
|
||||
|
||||
/**
|
||||
* Provide custom argument resolvers without overriding the built-in ones.
|
||||
* Configure resolvers for custom controller method arguments.
|
||||
*/
|
||||
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
protected void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.web.reactive.accept.CompositeContentTypeResolver;
|
|||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
||||
|
||||
/**
|
||||
* Defines callback methods to customize the configuration for Web Reactive
|
||||
|
@ -80,11 +81,10 @@ public interface WebFluxConfigurer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Provide custom controller method argument resolvers. Such resolvers do
|
||||
* not override and will be invoked after the built-in ones.
|
||||
* @param resolvers a list of resolvers to add
|
||||
* Configure resolvers for custom controller method arguments.
|
||||
* @param configurer to configurer to use
|
||||
*/
|
||||
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
default void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.springframework.util.CollectionUtils;
|
|||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
||||
|
||||
/**
|
||||
* A {@link WebFluxConfigurer} that delegates to one or more others.
|
||||
|
@ -70,8 +70,8 @@ public class WebFluxConfigurerComposite implements WebFluxConfigurer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
this.delegates.forEach(delegate -> delegate.addArgumentResolvers(resolvers));
|
||||
public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
||||
this.delegates.forEach(delegate -> delegate.configureArgumentResolvers(configurer));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2002-2017 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.web.reactive.result.method.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
|
||||
/**
|
||||
* Helps to configure resolvers for Controller method arguments.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ArgumentResolverConfigurer {
|
||||
|
||||
private final List<HandlerMethodArgumentResolver> customResolvers = new ArrayList<>(8);
|
||||
|
||||
|
||||
/**
|
||||
* Configure resolvers for custom controller method arguments.
|
||||
* @param resolver the resolver(s) to add
|
||||
*/
|
||||
public void addCustomResolver(HandlerMethodArgumentResolver... resolver) {
|
||||
Assert.notNull(resolver, "'resolvers' must not be null");
|
||||
this.customResolvers.addAll(Arrays.asList(resolver));
|
||||
}
|
||||
|
||||
|
||||
List<HandlerMethodArgumentResolver> getCustomResolvers() {
|
||||
return this.customResolvers;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@ package org.springframework.web.reactive.result.method.annotation;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -95,34 +96,36 @@ class ControllerMethodResolver {
|
|||
new LinkedHashMap<>(64);
|
||||
|
||||
|
||||
ControllerMethodResolver(List<HandlerMethodArgumentResolver> customResolvers,
|
||||
ControllerMethodResolver(ArgumentResolverConfigurer argumentResolverConfigurer,
|
||||
List<HttpMessageReader<?>> messageReaders, ReactiveAdapterRegistry reactiveRegistry,
|
||||
ConfigurableApplicationContext applicationContext) {
|
||||
|
||||
Assert.notNull(customResolvers, "'customResolvers' should not be null");
|
||||
Assert.notNull(argumentResolverConfigurer, "ArgumentResolverConfigurer is required");
|
||||
Assert.notNull(reactiveRegistry, "ReactiveAdapterRegistry is required");
|
||||
Assert.notNull(applicationContext, "ConfigurableApplicationContext is required");
|
||||
|
||||
ResolverRegistrar registrar = ResolverRegistrar.customResolvers(customResolvers).basic();
|
||||
ArgumentResolverRegistrar registrar;
|
||||
|
||||
registrar= ArgumentResolverRegistrar.configurer(argumentResolverConfigurer).basic();
|
||||
addResolversTo(registrar, reactiveRegistry, applicationContext);
|
||||
this.initBinderResolvers = registrar.getSyncResolvers();
|
||||
|
||||
registrar = ResolverRegistrar.customResolvers(customResolvers).modelAttributeSupport();
|
||||
registrar = ArgumentResolverRegistrar.configurer(argumentResolverConfigurer).modelAttributeSupport();
|
||||
addResolversTo(registrar, reactiveRegistry, applicationContext);
|
||||
this.modelAttributeResolvers = registrar.getResolvers();
|
||||
|
||||
registrar = ResolverRegistrar.customResolvers(customResolvers).fullSupport(messageReaders);
|
||||
registrar = ArgumentResolverRegistrar.configurer(argumentResolverConfigurer).fullSupport(messageReaders);
|
||||
addResolversTo(registrar, reactiveRegistry, applicationContext);
|
||||
this.requestMappingResolvers = registrar.getResolvers();
|
||||
|
||||
registrar = ResolverRegistrar.customResolvers(customResolvers).basic();
|
||||
registrar = ArgumentResolverRegistrar.configurer(argumentResolverConfigurer).basic();
|
||||
addResolversTo(registrar, reactiveRegistry, applicationContext);
|
||||
this.exceptionHandlerResolvers = registrar.getResolvers();
|
||||
|
||||
initControllerAdviceCaches(applicationContext);
|
||||
}
|
||||
|
||||
private void addResolversTo(ResolverRegistrar registrar,
|
||||
private void addResolversTo(ArgumentResolverRegistrar registrar,
|
||||
ReactiveAdapterRegistry reactiveRegistry, ConfigurableApplicationContext context) {
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
|
@ -319,7 +322,7 @@ class ControllerMethodResolver {
|
|||
(AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null);
|
||||
|
||||
|
||||
private static class ResolverRegistrar {
|
||||
private static class ArgumentResolverRegistrar {
|
||||
|
||||
private final List<HandlerMethodArgumentResolver> customResolvers;
|
||||
|
||||
|
@ -330,10 +333,10 @@ class ControllerMethodResolver {
|
|||
private final List<HandlerMethodArgumentResolver> result = new ArrayList<>();
|
||||
|
||||
|
||||
private ResolverRegistrar(List<HandlerMethodArgumentResolver> customResolvers,
|
||||
private ArgumentResolverRegistrar(ArgumentResolverConfigurer configurer,
|
||||
List<HttpMessageReader<?>> messageReaders, boolean modelAttribute) {
|
||||
|
||||
this.customResolvers = new ArrayList<>(customResolvers);
|
||||
this.customResolvers = configurer.getCustomResolvers();
|
||||
this.messageReaders = messageReaders != null ? new ArrayList<>(messageReaders) : null;
|
||||
this.modelAttributeSupported = modelAttribute;
|
||||
}
|
||||
|
@ -372,32 +375,32 @@ class ControllerMethodResolver {
|
|||
}
|
||||
|
||||
|
||||
public static Builder customResolvers(List<HandlerMethodArgumentResolver> customResolvers) {
|
||||
return new Builder(customResolvers);
|
||||
public static Builder configurer(ArgumentResolverConfigurer configurer) {
|
||||
return new Builder(configurer);
|
||||
}
|
||||
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final List<HandlerMethodArgumentResolver> customResolvers;
|
||||
private final ArgumentResolverConfigurer configurer;
|
||||
|
||||
|
||||
public Builder(List<HandlerMethodArgumentResolver> customResolvers) {
|
||||
this.customResolvers = new ArrayList<>(customResolvers);
|
||||
public Builder(ArgumentResolverConfigurer configurer) {
|
||||
this.configurer = configurer;
|
||||
}
|
||||
|
||||
|
||||
public ResolverRegistrar fullSupport(List<HttpMessageReader<?>> readers) {
|
||||
public ArgumentResolverRegistrar fullSupport(List<HttpMessageReader<?>> readers) {
|
||||
Assert.notEmpty(readers, "No message readers");
|
||||
return new ResolverRegistrar(this.customResolvers, readers, true);
|
||||
return new ArgumentResolverRegistrar(this.configurer, readers, true);
|
||||
}
|
||||
|
||||
public ResolverRegistrar modelAttributeSupport() {
|
||||
return new ResolverRegistrar(this.customResolvers, null, true);
|
||||
public ArgumentResolverRegistrar modelAttributeSupport() {
|
||||
return new ArgumentResolverRegistrar(this.configurer, null, true);
|
||||
}
|
||||
|
||||
public ResolverRegistrar basic() {
|
||||
return new ResolverRegistrar(this.customResolvers, null, false);
|
||||
public ArgumentResolverRegistrar basic() {
|
||||
return new ArgumentResolverRegistrar(this.configurer, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.apache.commons.logging.LogFactory;
|
|||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
@ -44,7 +43,6 @@ import org.springframework.web.method.HandlerMethod;
|
|||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.HandlerAdapter;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.reactive.result.method.InvocableHandlerMethod;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
|
@ -63,9 +61,9 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
|
||||
private WebBindingInitializer webBindingInitializer;
|
||||
|
||||
private ReactiveAdapterRegistry reactiveAdapterRegistry = new ReactiveAdapterRegistry();
|
||||
private ArgumentResolverConfigurer argumentResolverConfigurer;
|
||||
|
||||
private final List<HandlerMethodArgumentResolver> customArgumentResolvers = new ArrayList<>(8);
|
||||
private ReactiveAdapterRegistry reactiveAdapterRegistry;
|
||||
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
|
@ -117,6 +115,21 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
return this.webBindingInitializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure resolvers for controller method arguments.
|
||||
*/
|
||||
public void setArgumentResolverConfigurer(ArgumentResolverConfigurer configurer) {
|
||||
Assert.notNull(configurer, "ArgumentResolverConfigurer is required");
|
||||
this.argumentResolverConfigurer = configurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured resolvers for controller method arguments.
|
||||
*/
|
||||
public ArgumentResolverConfigurer getArgumentResolverConfigurer() {
|
||||
return this.argumentResolverConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the registry for adapting various reactive types.
|
||||
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
|
||||
|
@ -133,21 +146,6 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
return this.reactiveAdapterRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure resolvers for custom controller method arguments.
|
||||
*/
|
||||
public void setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
this.customArgumentResolvers.clear();
|
||||
this.customArgumentResolvers.addAll(resolvers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured custom argument resolvers.
|
||||
*/
|
||||
public List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() {
|
||||
return this.customArgumentResolvers;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ConfigurableApplicationContext} is expected for resolving
|
||||
* expressions in method argument default values as well as for
|
||||
|
@ -164,18 +162,22 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
|
|||
return this.applicationContext;
|
||||
}
|
||||
|
||||
public ConfigurableBeanFactory getBeanFactory() {
|
||||
return this.applicationContext.getBeanFactory();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
this.methodResolver = new ControllerMethodResolver(getCustomArgumentResolvers(),
|
||||
getMessageReaders(), getReactiveAdapterRegistry(), getApplicationContext());
|
||||
if (this.argumentResolverConfigurer == null) {
|
||||
this.argumentResolverConfigurer = new ArgumentResolverConfigurer();
|
||||
}
|
||||
|
||||
this.modelInitializer = new ModelInitializer(getReactiveAdapterRegistry());
|
||||
if (this.reactiveAdapterRegistry == null) {
|
||||
this.reactiveAdapterRegistry = new ReactiveAdapterRegistry();
|
||||
}
|
||||
|
||||
this.methodResolver = new ControllerMethodResolver(this.argumentResolverConfigurer,
|
||||
this.messageReaders, this.reactiveAdapterRegistry, this.applicationContext);
|
||||
|
||||
this.modelInitializer = new ModelInitializer(this.reactiveAdapterRegistry);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public class DelegatingWebFluxConfigurationTests {
|
|||
verify(webFluxConfigurer).getValidator();
|
||||
verify(webFluxConfigurer).getMessageCodesResolver();
|
||||
verify(webFluxConfigurer).addFormatters(formatterRegistry.capture());
|
||||
verify(webFluxConfigurer).addArgumentResolvers(any());
|
||||
verify(webFluxConfigurer).configureArgumentResolvers(any());
|
||||
|
||||
assertSame(formatterRegistry.getValue(), initializerConversionService);
|
||||
assertEquals(9, codecsConfigurer.getValue().getReaders().size());
|
||||
|
|
|
@ -67,8 +67,9 @@ public class ControllerMethodResolverTests {
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
List<HandlerMethodArgumentResolver> customResolvers =
|
||||
Arrays.asList(new CustomArgumentResolver(), new CustomSyncArgumentResolver());
|
||||
ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer();
|
||||
configurer.addCustomResolver(new CustomArgumentResolver());
|
||||
configurer.addCustomResolver(new CustomSyncArgumentResolver());
|
||||
|
||||
List<HttpMessageReader<?>> messageReaders = Arrays.asList(
|
||||
new DecoderHttpMessageReader<>(new ByteArrayDecoder()),
|
||||
|
@ -79,7 +80,7 @@ public class ControllerMethodResolverTests {
|
|||
applicationContext.refresh();
|
||||
|
||||
this.methodResolver = new ControllerMethodResolver(
|
||||
customResolvers, messageReaders, new ReactiveAdapterRegistry(), applicationContext);
|
||||
configurer, messageReaders, new ReactiveAdapterRegistry(), applicationContext);
|
||||
|
||||
Method method = ResolvableMethod.on(TestController.class).mockCall(TestController::handle).method();
|
||||
this.handlerMethod = new HandlerMethod(new TestController(), method);
|
||||
|
|
Loading…
Reference in New Issue