Support <ref> for arg resolvers return value handlers
Issue: SPR-11927
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user