SPR-8234 Switch to strongly typed custom argument resolvers property

This commit is contained in:
Rossen Stoyanchev 2011-04-11 15:50:04 +00:00
parent 54bbcf3a42
commit 23e37b6842
5 changed files with 49 additions and 48 deletions

View File

@ -16,13 +16,20 @@
package org.springframework.web.servlet.config; package org.springframework.web.servlet.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.config.AbstractSpecificationBeanDefinitionParser; import org.springframework.context.config.AbstractSpecificationBeanDefinitionParser;
import org.springframework.context.config.FeatureSpecification; import org.springframework.context.config.FeatureSpecification;
import org.springframework.util.ClassUtils;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter;
import org.w3c.dom.Element; import org.w3c.dom.Element;
/** /**
@ -63,14 +70,15 @@ class AnnotationDrivenBeanDefinitionParser extends AbstractSpecificationBeanDefi
} }
Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers"); Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers");
if (resolversElement != null) { if (resolversElement != null) {
spec.argumentResolvers(extractBeanSubElements(resolversElement, parserContext)); ManagedList<BeanDefinitionHolder> beanDefs = extractBeanSubElements(resolversElement, parserContext);
spec.argumentResolvers(wrapWebArgumentResolverBeanDefs(beanDefs));
} }
return spec; return spec;
} }
private ManagedList<? super Object> extractBeanSubElements(Element parentElement, ParserContext parserContext) { private ManagedList<BeanDefinitionHolder> extractBeanSubElements(Element parentElement, ParserContext parserContext) {
ManagedList<? super Object> list = new ManagedList<Object>(); ManagedList<BeanDefinitionHolder> list = new ManagedList<BeanDefinitionHolder>();
list.setSource(parserContext.extractSource(parentElement)); list.setSource(parserContext.extractSource(parentElement));
for (Element beanElement : DomUtils.getChildElementsByTagName(parentElement, "bean")) { for (Element beanElement : DomUtils.getChildElementsByTagName(parentElement, "bean")) {
BeanDefinitionHolder beanDef = parserContext.getDelegate().parseBeanDefinitionElement(beanElement); BeanDefinitionHolder beanDef = parserContext.getDelegate().parseBeanDefinitionElement(beanElement);
@ -80,4 +88,23 @@ class AnnotationDrivenBeanDefinitionParser extends AbstractSpecificationBeanDefi
return list; return list;
} }
private ManagedList<BeanDefinitionHolder> wrapWebArgumentResolverBeanDefs(List<BeanDefinitionHolder> beanDefs) {
ManagedList<BeanDefinitionHolder> result = new ManagedList<BeanDefinitionHolder>();
for (BeanDefinitionHolder beanDef : beanDefs) {
String className = beanDef.getBeanDefinition().getBeanClassName();
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
if (WebArgumentResolver.class.isAssignableFrom(clazz)) {
RootBeanDefinition adapter = new RootBeanDefinition(ServletWebArgumentResolverAdapter.class);
adapter.getConstructorArgumentValues().addIndexedArgumentValue(0, beanDef);
result.add(new BeanDefinitionHolder(adapter, beanDef.getBeanName() + "Adapter"));
}
else {
result.add(beanDef);
}
}
return result;
}
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.springframework.web.servlet.config; package org.springframework.web.servlet.config;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.ProblemCollector; import org.springframework.beans.factory.parsing.ProblemCollector;
import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedList;
import org.springframework.context.config.AbstractFeatureSpecification; import org.springframework.context.config.AbstractFeatureSpecification;
@ -145,8 +146,8 @@ public final class MvcAnnotationDriven extends AbstractFeatureSpecification {
return this; return this;
} }
void messageConverters(ManagedList<? super Object> messageConverters) { void messageConverters(ManagedList<BeanDefinitionHolder> converterBeanDefinitions) {
this.messageConverters = messageConverters; this.messageConverters.addAll(converterBeanDefinitions);
} }
ManagedList<?> messageConverters() { ManagedList<?> messageConverters() {
@ -183,8 +184,8 @@ public final class MvcAnnotationDriven extends AbstractFeatureSpecification {
return this; return this;
} }
void argumentResolvers(ManagedList<? super Object> argumentResolvers) { void argumentResolvers(ManagedList<BeanDefinitionHolder> resolverBeanDefinitions) {
this.argumentResolvers = argumentResolvers; this.argumentResolvers.addAll(resolverBeanDefinitions);
} }
ManagedList<?> argumentResolvers() { ManagedList<?> argumentResolvers() {

View File

@ -175,28 +175,13 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda
* Set one or more custom argument resolvers to use with {@link RequestMapping}, {@link ModelAttribute}, and * Set one or more custom argument resolvers to use with {@link RequestMapping}, {@link ModelAttribute}, and
* {@link InitBinder} methods. Custom argument resolvers are given a chance to resolve argument values * {@link InitBinder} methods. Custom argument resolvers are given a chance to resolve argument values
* ahead of the standard argument resolvers registered by default. * ahead of the standard argument resolvers registered by default.
* <p>Argument resolvers of type {@link HandlerMethodArgumentResolver} and {@link WebArgumentResolver} are * <p>An existing {@link WebArgumentResolver} can either adapted with {@link ServletWebArgumentResolverAdapter}
* accepted with instances of the latter adapted via {@link ServletWebArgumentResolverAdapter}. For new * or preferably converted to a {@link HandlerMethodArgumentResolver} instead.
* implementations {@link HandlerMethodArgumentResolver} should be preferred over {@link WebArgumentResolver}.
*/ */
public void setCustomArgumentResolvers(List<?> argumentResolvers) { public void setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
if (argumentResolvers == null) { if (argumentResolvers != null) {
return; this.customArgumentResolvers.addAll(argumentResolvers);
} }
List<HandlerMethodArgumentResolver> adaptedResolvers = new ArrayList<HandlerMethodArgumentResolver>();
for (Object resolver : argumentResolvers) {
if (resolver instanceof WebArgumentResolver) {
adaptedResolvers.add(new ServletWebArgumentResolverAdapter((WebArgumentResolver) resolver));
}
else if (resolver instanceof HandlerMethodArgumentResolver) {
adaptedResolvers.add((HandlerMethodArgumentResolver) resolver);
}
else {
throw new IllegalArgumentException(
"An argument resolver must be a HandlerMethodArgumentResolver or a WebArgumentResolver");
}
}
this.customArgumentResolvers.addAll(adaptedResolvers);
} }
/** /**

View File

@ -115,28 +115,13 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle
/** /**
* Set one or more custom argument resolvers to use with {@link ExceptionHandler} methods. Custom argument resolvers * Set one or more custom argument resolvers to use with {@link ExceptionHandler} methods. Custom argument resolvers
* are given a chance to resolve argument values ahead of the standard argument resolvers registered by default. * are given a chance to resolve argument values ahead of the standard argument resolvers registered by default.
* <p>Argument resolvers of type {@link HandlerMethodArgumentResolver} and {@link WebArgumentResolver} are * <p>An existing {@link WebArgumentResolver} can either adapted with {@link ServletWebArgumentResolverAdapter}
* accepted with instances of the latter adapted via {@link ServletWebArgumentResolverAdapter}. For new * or preferably converted to a {@link HandlerMethodArgumentResolver} instead.
* implementations {@link HandlerMethodArgumentResolver} should be preferred over {@link WebArgumentResolver}.
*/ */
public void setCustomArgumentResolvers(List<?> argumentResolvers) { public void setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
if (argumentResolvers == null) { if (argumentResolvers != null) {
return; this.customArgumentResolvers.addAll(argumentResolvers);
} }
List<HandlerMethodArgumentResolver> adaptedResolvers = new ArrayList<HandlerMethodArgumentResolver>();
for (Object resolver : argumentResolvers) {
if (resolver instanceof WebArgumentResolver) {
adaptedResolvers.add(new ServletWebArgumentResolverAdapter((WebArgumentResolver) resolver));
}
else if (resolver instanceof HandlerMethodArgumentResolver) {
adaptedResolvers.add((HandlerMethodArgumentResolver) resolver);
}
else {
throw new IllegalArgumentException(
"An argument resolver must be a HandlerMethodArgumentResolver or a WebArgumentResolver");
}
}
this.customArgumentResolvers.addAll(adaptedResolvers);
} }
/** /**

View File

@ -122,6 +122,7 @@ import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.support.StringMultipartFileEditor; import org.springframework.web.multipart.support.StringMultipartFileEditor;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@ -129,6 +130,7 @@ import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver; import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver; import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.util.NestedServletException; import org.springframework.web.util.NestedServletException;
@ -570,7 +572,8 @@ public class ServletHandlerMethodTests {
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)); wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerMethodAdapter.class); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerMethodAdapter.class);
adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer()); adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer());
WebArgumentResolver[] argumentResolvers = new WebArgumentResolver[] {new MySpecialArgumentResolver()}; List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
argumentResolvers.add(new ServletWebArgumentResolverAdapter(new MySpecialArgumentResolver()));
adapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers); adapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
wac.registerBeanDefinition("handlerAdapter", adapterDef); wac.registerBeanDefinition("handlerAdapter", adapterDef);
} }