Browse Source

Support <ref> for arg resolvers return value handlers

Issue: SPR-11927
pull/589/head
Rossen Stoyanchev 12 years ago
parent
commit
fa33ed4b4b
  1. 63
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
  2. 21
      spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd
  3. 23
      spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java
  4. 17
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-argument-resolvers-references.xml
  5. 3
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-argument-resolvers.xml
  6. 5
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-return-value-handlers.xml

63
spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java

@ -471,21 +471,34 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
private ManagedList<?> getArgumentResolvers(Element element, ParserContext parserContext) { private ManagedList<?> getArgumentResolvers(Element element, ParserContext parserContext) {
Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers"); Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers");
if (resolversElement != null) { if (resolversElement != null) {
ManagedList<BeanDefinitionHolder> argumentResolvers = extractBeanSubElements(resolversElement, parserContext); ManagedList<Object> resolvers = extractBeanSubElements(resolversElement, parserContext);
ManagedList<BeanMetadataElement> customAndReferencedResolvers = new ManagedList<BeanMetadataElement>(); return wrapLegacyResolvers(resolvers, parserContext);
customAndReferencedResolvers.addAll(wrapWebArgumentResolverBeanDefs(argumentResolvers, parserContext));
customAndReferencedResolvers.addAll(extractBeanRefSubElements(resolversElement, parserContext));
return customAndReferencedResolvers;
} }
return null; return null;
} }
private ManagedList<?> getReturnValueHandlers(Element element, ParserContext parserContext) { private ManagedList<Object> wrapLegacyResolvers(List<Object> list, ParserContext context) {
Element handlersElement = DomUtils.getChildElementByTagName(element, "return-value-handlers"); ManagedList<Object> result = new ManagedList<Object>();
if (handlersElement != null) { for (Object object : list) {
return extractBeanSubElements(handlersElement, parserContext); if (object instanceof BeanDefinitionHolder) {
BeanDefinitionHolder beanDef = (BeanDefinitionHolder) object;
String className = beanDef.getBeanDefinition().getBeanClassName();
Class<?> clazz = ClassUtils.resolveClassName(className, context.getReaderContext().getBeanClassLoader());
if (WebArgumentResolver.class.isAssignableFrom(clazz)) {
RootBeanDefinition adapter = new RootBeanDefinition(ServletWebArgumentResolverAdapter.class);
adapter.getConstructorArgumentValues().addIndexedArgumentValue(0, beanDef);
result.add(new BeanDefinitionHolder(adapter, beanDef.getBeanName() + "Adapter"));
continue;
}
}
result.add(object);
} }
return null; return result;
}
private ManagedList<?> getReturnValueHandlers(Element element, ParserContext parserContext) {
Element handlers = DomUtils.getChildElementByTagName(element, "return-value-handlers");
return (handlers != null ? extractBeanSubElements(handlers, parserContext) : null);
} }
private ManagedList<?> getMessageConverters(Element element, Object source, ParserContext parserContext) { private ManagedList<?> getMessageConverters(Element element, Object source, ParserContext parserContext) {
@ -536,13 +549,12 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
} }
private ManagedList<BeanDefinitionHolder> extractBeanSubElements(Element parentElement, ParserContext parserContext) { private ManagedList<Object> extractBeanSubElements(Element parentElement, ParserContext parserContext) {
ManagedList<BeanDefinitionHolder> list = new ManagedList<BeanDefinitionHolder>(); ManagedList<Object> list = new ManagedList<Object>();
list.setSource(parserContext.extractSource(parentElement)); list.setSource(parserContext.extractSource(parentElement));
for (Element beanElement : DomUtils.getChildElementsByTagName(parentElement, "bean")) { for (Element beanElement : DomUtils.getChildElementsByTagName(parentElement, "bean", "ref")) {
BeanDefinitionHolder beanDef = parserContext.getDelegate().parseBeanDefinitionElement(beanElement); Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
beanDef = parserContext.getDelegate().decorateBeanDefinitionIfRequired(beanElement, beanDef); list.add(object);
list.add(beanDef);
} }
return list; return list;
} }
@ -566,25 +578,6 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
return list; return list;
} }
private ManagedList<BeanDefinitionHolder> wrapWebArgumentResolverBeanDefs(
List<BeanDefinitionHolder> beanDefs, ParserContext parserContext) {
ManagedList<BeanDefinitionHolder> result = new ManagedList<BeanDefinitionHolder>();
for (BeanDefinitionHolder beanDef : beanDefs) {
String className = beanDef.getBeanDefinition().getBeanClassName();
Class<?> clazz = ClassUtils.resolveClassName(className, parserContext.getReaderContext().getBeanClassLoader());
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;
}
/** /**
* A FactoryBean for a CompositeUriComponentsContributor that obtains the * A FactoryBean for a CompositeUriComponentsContributor that obtains the

21
spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd

@ -138,8 +138,7 @@
<xsd:element ref="beans:ref" minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="beans:ref" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
A reference to a HandlerMethodArgumentResolver bean definition. Expects a HandlerMethodArgumentResolver instance, A reference to a HandlerMethodArgumentResolver bean definition.
WebArgumentResolver instances has to be wrapped with a ServletWebArgumentResolverAdapter
]]></xsd:documentation> ]]></xsd:documentation>
<xsd:appinfo> <xsd:appinfo>
<tool:annotation kind="ref"> <tool:annotation kind="ref">
@ -160,15 +159,27 @@
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element ref="beans:bean" minOccurs="1" maxOccurs="unbounded"> <xsd:element ref="beans:bean" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The HandlerMethodReturnValueHandler bean definition. The HandlerMethodReturnValueHandler bean definition.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:element> </xsd:element>
</xsd:sequence> <xsd:element ref="beans:ref" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to a HandlerMethodReturnValueHandler bean definition.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="java:org.springframework.web.method.support.HandlerMethodReturnValueHandler" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:choice>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="async-support" minOccurs="0"> <xsd:element name="async-support" minOccurs="0">

23
spring-webmvc/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java

@ -117,26 +117,13 @@ public class AnnotationDrivenBeanDefinitionParserTests {
assertNotNull(value); assertNotNull(value);
assertTrue(value instanceof List); assertTrue(value instanceof List);
List<HandlerMethodArgumentResolver> resolvers = (List<HandlerMethodArgumentResolver>) value; List<HandlerMethodArgumentResolver> resolvers = (List<HandlerMethodArgumentResolver>) value;
assertEquals(2, resolvers.size()); assertEquals(3, resolvers.size());
assertTrue(resolvers.get(0) instanceof ServletWebArgumentResolverAdapter); assertTrue(resolvers.get(0) instanceof ServletWebArgumentResolverAdapter);
assertTrue(resolvers.get(1) instanceof TestHandlerMethodArgumentResolver); assertTrue(resolvers.get(1) instanceof TestHandlerMethodArgumentResolver);
assertTrue(resolvers.get(2) instanceof TestHandlerMethodArgumentResolver);
assertNotSame(resolvers.get(1), resolvers.get(2));
} }
@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<HandlerMethodArgumentResolver> resolvers = (List<HandlerMethodArgumentResolver>) value;
assertEquals(2, resolvers.size());
assertTrue(resolvers.get(0) instanceof ServletWebArgumentResolverAdapter);
assertTrue(resolvers.get(1) instanceof TestHandlerMethodArgumentResolver);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void testReturnValueHandlers() { public void testReturnValueHandlers() {
@ -147,8 +134,10 @@ public class AnnotationDrivenBeanDefinitionParserTests {
assertNotNull(value); assertNotNull(value);
assertTrue(value instanceof List); assertTrue(value instanceof List);
List<HandlerMethodReturnValueHandler> handlers = (List<HandlerMethodReturnValueHandler>) value; List<HandlerMethodReturnValueHandler> handlers = (List<HandlerMethodReturnValueHandler>) value;
assertEquals(1, handlers.size()); assertEquals(2, handlers.size());
assertEquals(TestHandlerMethodReturnValueHandler.class, handlers.get(0).getClass()); assertEquals(TestHandlerMethodReturnValueHandler.class, handlers.get(0).getClass());
assertEquals(TestHandlerMethodReturnValueHandler.class, handlers.get(1).getClass());
assertNotSame(handlers.get(0), handlers.get(1));
} }
@Test @Test

17
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-argument-resolvers-references.xml

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.web.servlet.config.TestWebArgumentResolver"/>
<ref bean="customArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
<bean id="customArgumentResolver" class="org.springframework.web.servlet.config.TestHandlerMethodArgumentResolver"/>
</beans>

3
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-argument-resolvers.xml

@ -9,7 +9,10 @@
<mvc:argument-resolvers> <mvc:argument-resolvers>
<bean class="org.springframework.web.servlet.config.TestWebArgumentResolver"/> <bean class="org.springframework.web.servlet.config.TestWebArgumentResolver"/>
<bean class="org.springframework.web.servlet.config.TestHandlerMethodArgumentResolver"/> <bean class="org.springframework.web.servlet.config.TestHandlerMethodArgumentResolver"/>
<ref bean="customArgumentResolver" />
</mvc:argument-resolvers> </mvc:argument-resolvers>
</mvc:annotation-driven> </mvc:annotation-driven>
<bean id="customArgumentResolver" class="org.springframework.web.servlet.config.TestHandlerMethodArgumentResolver"/>
</beans> </beans>

5
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-return-value-handlers.xml

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
@ -8,7 +8,10 @@
<mvc:annotation-driven> <mvc:annotation-driven>
<mvc:return-value-handlers> <mvc:return-value-handlers>
<bean class="org.springframework.web.servlet.config.TestHandlerMethodReturnValueHandler"/> <bean class="org.springframework.web.servlet.config.TestHandlerMethodReturnValueHandler"/>
<ref bean="customHandler" />
</mvc:return-value-handlers> </mvc:return-value-handlers>
</mvc:annotation-driven> </mvc:annotation-driven>
<bean id="customHandler" class="org.springframework.web.servlet.config.TestHandlerMethodReturnValueHandler"/>
</beans> </beans>

Loading…
Cancel
Save