diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java index afdb148516d..aa69d0d9b21 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java @@ -19,14 +19,14 @@ package org.springframework.web.servlet.config; import java.util.List; import java.util.Properties; -import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice; -import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.w3c.dom.Element; +import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.BeanReference; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.parsing.CompositeComponentDefinition; @@ -44,11 +44,13 @@ import org.springframework.http.converter.ResourceHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter; import org.springframework.http.converter.feed.RssChannelHttpMessageConverter; +import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter; import org.springframework.http.converter.xml.SourceHttpMessageConverter; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.springframework.web.HttpRequestHandler; import org.springframework.web.accept.ContentNegotiationManager; @@ -69,6 +71,7 @@ import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter; import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @@ -138,6 +141,7 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv * @author Arjen Poutsma * @author Rossen Stoyanchev * @author Brian Clozel + * @author Agim Emruli * @since 3.0 */ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { @@ -468,7 +472,10 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers"); if (resolversElement != null) { ManagedList argumentResolvers = extractBeanSubElements(resolversElement, parserContext); - return wrapWebArgumentResolverBeanDefs(argumentResolvers, parserContext); + ManagedList customAndReferencedResolvers = new ManagedList(); + customAndReferencedResolvers.addAll(wrapWebArgumentResolverBeanDefs(argumentResolvers, parserContext)); + customAndReferencedResolvers.addAll(extractBeanRefSubElements(resolversElement, parserContext)); + return customAndReferencedResolvers; } return null; } @@ -540,6 +547,25 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { return list; } + private ManagedList extractBeanRefSubElements(Element parentElement, ParserContext parserContext){ + ManagedList list = new ManagedList(); + list.setSource(parserContext.extractSource(parentElement)); + for (Element refElement : DomUtils.getChildElementsByTagName(parentElement, "ref")) { + BeanReference reference; + if (StringUtils.hasText("bean")) { + reference = new RuntimeBeanReference(refElement.getAttribute("bean"),false); + list.add(reference); + }else if(StringUtils.hasText("parent")){ + reference = new RuntimeBeanReference(refElement.getAttribute("parent"),true); + list.add(reference); + }else{ + parserContext.getReaderContext().error("'bean' or 'parent' attribute is required for element", + parserContext.extractSource(parentElement)); + } + } + return list; + } + private ManagedList wrapWebArgumentResolverBeanDefs( List beanDefs, ParserContext parserContext) { diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd index ad1cd6ab5a1..f992b0793b2 100644 --- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd +++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd @@ -127,15 +127,28 @@ ]]> - - + + - + + + + + + + + + + + diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java index 7865cdf69ec..3f435f8b3d3 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java @@ -38,9 +38,9 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; +import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.ServletWebArgumentResolverAdapter; @@ -52,6 +52,7 @@ import static org.junit.Assert.*; * Test fixture for the configuration in mvc-config-annotation-driven.xml. * @author Rossen Stoyanchev * @author Brian Clozel + * @author Agim Emruli */ public class AnnotationDrivenBeanDefinitionParserTests { @@ -121,6 +122,21 @@ public class AnnotationDrivenBeanDefinitionParserTests { assertTrue(resolvers.get(1) instanceof TestHandlerMethodArgumentResolver); } + @SuppressWarnings("unchecked") + @Test + public void testArgumentResolversWithReference() { + loadBeanDefinitions("mvc-config-argument-resolvers-references.xml"); + RequestMappingHandlerAdapter adapter = appContext.getBean(RequestMappingHandlerAdapter.class); + assertNotNull(adapter); + Object value = new DirectFieldAccessor(adapter).getPropertyValue("customArgumentResolvers"); + assertNotNull(value); + assertTrue(value instanceof List); + List resolvers = (List) value; + assertEquals(2, resolvers.size()); + assertTrue(resolvers.get(0) instanceof ServletWebArgumentResolverAdapter); + assertTrue(resolvers.get(1) instanceof TestHandlerMethodArgumentResolver); + } + @SuppressWarnings("unchecked") @Test public void testReturnValueHandlers() { diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-argument-resolvers-references.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-argument-resolvers-references.xml new file mode 100644 index 00000000000..e7a61fb2cda --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-argument-resolvers-references.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + +