提交 cd2fee03 编写于 作者: R Rossen Stoyanchev

SPR-8783 Update javadoc of MVC's AnnotationDrivenBeanDefinitionParser

上级 bba8bb6e
......@@ -27,7 +27,7 @@ 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.ParserContext;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
......@@ -41,12 +41,21 @@ import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.util.xml.DomUtils;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.MappedInterceptor;
import org.springframework.web.servlet.mvc.Controller;
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.RequestMappingHandlerAdapter;
......@@ -56,27 +65,52 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
import org.w3c.dom.Element;
/**
* {@link BeanDefinitionParser} that parses the {@code annotation-driven} element to configure a Spring MVC web
* application.
* A {@link BeanDefinitionParser} that provides the configuration for the
* {@code <annotation-driven/>} MVC namespace element.
*
* <p>Responsible for:
* <ol>
* <li>Registering a {@code DefaultAnnotationHandlerMapping} bean for mapping HTTP Servlet Requests to {@code @Controller} methods
* using {@code @RequestMapping} annotations.
* <li>Registering an {@code AnnotationMethodHandlerAdapter} bean for invoking annotated {@code @Controller} methods.
* Will configure the {@code HandlerAdapter}'s <code>webBindingInitializer</code> property for centrally configuring
* {@code @Controller} {@code DataBinder} instances:
* <p>This class registers the following {@link HandlerMapping}s:</p>
* <ul>
* <li>Configures the conversionService if specified, otherwise defaults to a fresh {@link ConversionService} instance
* created by the default {@link FormattingConversionServiceFactoryBean}.
* <li>Configures the validator if specified, otherwise defaults to a fresh {@link Validator} instance created by the
* default {@link LocalValidatorFactoryBean} <em>if the JSR-303 API is present on the classpath</em>.
* <li>Configures standard {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters},
* including the {@link Jaxb2RootElementHttpMessageConverter} <em>if JAXB2 is present on the classpath</em>, and
* the {@link MappingJacksonHttpMessageConverter} <em>if Jackson is present on the classpath</em>.
* <li>{@link RequestMappingHandlerMapping}
* ordered at 0 for mapping requests to annotated controller methods.
* <li>{@link BeanNameUrlHandlerMapping}
* ordered at 2 to map URL paths to controller bean names.
* </ul>
* </ol>
*
* <p><strong>Note:</strong> Additional HandlerMappings may be registered
* as a result of using the {@code <view-controller>} or the
* {@code <resources>} MVC namespace elements.
*
* <p>This class registers the following {@link HandlerAdapter}s:
* <ul>
* <li>{@link RequestMappingHandlerAdapter}
* for processing requests with annotated controller methods.
* <li>{@link HttpRequestHandlerAdapter}
* for processing requests with {@link HttpRequestHandler}s.
* <li>{@link SimpleControllerHandlerAdapter}
* for processing requests with interface-based {@link Controller}s.
* </ul>
*
* <p>This class registers the following {@link HandlerExceptionResolver}s:
* <ul>
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
* through @{@link ExceptionHandler} methods.
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
* with @{@link ResponseStatus}.
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
* exception types
* </ul>
*
* <p>Both the {@link RequestMappingHandlerAdapter} and the
* {@link ExceptionHandlerExceptionResolver} are configured with default
* instances of the following kind, unless custom instances are provided:
* <ul>
* <li>A {@link DefaultFormattingConversionService}
* <li>A {@link LocalValidatorFactoryBean} if a JSR-303 implementation is
* available on the classpath
* <li>A range of {@link HttpMessageConverter}s depending on what 3rd party
* libraries are available on the classpath.
* </ul>
*
* @author Keith Donald
* @author Juergen Hoeller
* @author Arjen Poutsma
......@@ -178,11 +212,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Ensure default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
parserContext.popAndRegisterContainingComponent();
......
......@@ -69,11 +69,8 @@ class DefaultServletHandlerBeanDefinitionParser implements BeanDefinitionParser
parserContext.getRegistry().registerBeanDefinition(handlerMappingBeanName, handlerMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingBeanName));
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Register HttpRequestHandlerAdapter
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
return null;
}
......
......@@ -25,55 +25,68 @@ import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
/**
* Convenience methods for MVC namespace handlers.
* Convenience methods for use in MVC namespace BeanDefinitionParsers.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
abstract class MvcNamespaceUtils {
private static final String BEAN_NAME_URL_HANDLER_MAPPING =
"org.springframework.web.servlet.handler.beanNameUrlHandlerMapping";
private static final String BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME =
BeanNameUrlHandlerMapping.class.getName();
private static final String VIEW_CONTROLLER_HANDLER_ADAPTER =
"org.springframework.web.servlet.config.viewControllerHandlerAdapter";
private static final String SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME =
SimpleControllerHandlerAdapter.class.getName();
private static final String HTTP_REQUEST_HANDLER_ADAPTER =
"org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter";
private static final String HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME =
HttpRequestHandlerAdapter.class.getName();
public static void registerDefaultHandlerAdapters(ParserContext parserContext, Object source) {
public static void registerDefaultComponents(ParserContext parserContext, Object source) {
registerBeanNameUrlHandlerMapping(parserContext, source);
registerHttpRequestHandlerAdapter(parserContext, source);
registerSimpleControllerHandlerAdapter(parserContext, source);
}
public static void registerBeanNameUrlHandlerMapping(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING)){
/**
* Registers an {@link HttpRequestHandlerAdapter} under a well-known
* name unless already registered.
*/
private static void registerBeanNameUrlHandlerMapping(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME)){
RootBeanDefinition beanNameMappingDef = new RootBeanDefinition(BeanNameUrlHandlerMapping.class);
beanNameMappingDef.setSource(source);
beanNameMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanNameMappingDef.getPropertyValues().add("order", 2); // consistent with MvcConfiguration
parserContext.getRegistry().registerBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING, beanNameMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(beanNameMappingDef, BEAN_NAME_URL_HANDLER_MAPPING));
beanNameMappingDef.getPropertyValues().add("order", 2); // consistent with WebMvcConfigurationSupport
parserContext.getRegistry().registerBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME, beanNameMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(beanNameMappingDef, BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME));
}
}
public static void registerHttpRequestHandlerAdapter(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER)) {
/**
* Registers an {@link HttpRequestHandlerAdapter} under a well-known
* name unless already registered.
*/
private static void registerHttpRequestHandlerAdapter(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME)) {
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HTTP_REQUEST_HANDLER_ADAPTER));
parserContext.getRegistry().registerBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME));
}
}
public static void registerSimpleControllerHandlerAdapter(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(VIEW_CONTROLLER_HANDLER_ADAPTER)) {
/**
* Registers a {@link SimpleControllerHandlerAdapter} under a well-known
* name unless already registered.
*/
private static void registerSimpleControllerHandlerAdapter(ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME)) {
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(SimpleControllerHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(VIEW_CONTROLLER_HANDLER_ADAPTER, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, VIEW_CONTROLLER_HANDLER_ADAPTER));
parserContext.getRegistry().registerBeanDefinition(SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME));
}
}
......
......@@ -73,11 +73,9 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
parserContext.getRegistry().registerBeanDefinition(beanName, handlerMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, beanName));
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
// Register HttpRequestHandlerAdapter
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
return null;
}
......
......@@ -49,11 +49,8 @@ class ViewControllerBeanDefinitionParser implements BeanDefinitionParser {
// Register SimpleUrlHandlerMapping for view controllers
BeanDefinition handlerMappingDef = registerHandlerMapping(parserContext, source);
// Ensure BeanNameUrlHandlerMapping is not "turned off" (SPR-8289)
MvcNamespaceUtils.registerBeanNameUrlHandlerMapping(parserContext, source);
// Register SimpleControllerHandlerAdapter
MvcNamespaceUtils.registerDefaultHandlerAdapters(parserContext, source);
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
// Create view controller bean definition
RootBeanDefinition viewControllerDef = new RootBeanDefinition(ParameterizableViewController.class);
......
......@@ -28,10 +28,9 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
/**
* A sub-class of {@link WebMvcConfigurationSupport} that detects beans of
* type {@link WebMvcConfigurer}. Each {@link WebMvcConfigurer} is given a
* chance to customize the Spring MVC configuration provided through
* {@link WebMvcConfigurationSupport}.
* Extends {@link WebMvcConfigurationSupport} with the ability to detect beans
* of type {@link WebMvcConfigurer} and give them a chance to customize the
* provided configuration by delegating to them at the appropriate times.
*
* @author Rossen Stoyanchev
* @since 3.1
......
......@@ -48,6 +48,7 @@ import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
......@@ -55,7 +56,6 @@ import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerMapping;
......@@ -73,17 +73,13 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
/**
* A base class that provides configuration for Spring MVC applications
* by registering Spring MVC infrastructure components detected by the
* {@link DispatcherServlet}. An application configuration class is not required
* to extend this class. A more likely place to start is to annotate
* an @{@link Configuration} class with @{@link EnableWebMvc}
* (see @{@link EnableWebMvc} and {@link WebMvcConfigurer} for details).
*
* <p>If the customization options available with use of @{@link EnableWebMvc}
* are not enough, consider extending directly from this class and override the
* appropriate methods. Remember to add @{@link Configuration} to your subclass
* and @{@link Bean} to any superclass @{@link Bean} methods you override.
* This is the main class providing the configuration behind the MVC Java config.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class. An alternative more
* advanced option is to extend directly from this class and override methods as
* necessary remembering to add {@link Configuration @Configuration} to the
* subclass and {@link Bean @Bean} to overridden {@link Bean @Bean} methods.
* For more details see the Javadoc of {@link EnableWebMvc @EnableWebMvc}.
*
* <p>This class registers the following {@link HandlerMapping}s:</p>
* <ul>
......@@ -120,14 +116,17 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
* exception types
* </ul>
*
* <p>Registers these other instances:
* <p>Both the {@link RequestMappingHandlerAdapter} and the
* {@link ExceptionHandlerExceptionResolver} are configured with default
* instances of the following kind, unless custom instances are provided:
* <ul>
* <li>{@link FormattingConversionService}
* for use with annotated controller methods and the spring:eval JSP tag.
* <li>{@link Validator}
* for validating model attributes on annotated controller methods.
* <li>A {@link DefaultFormattingConversionService}
* <li>A {@link LocalValidatorFactoryBean} if a JSR-303 implementation is
* available on the classpath
* <li>A range of {@link HttpMessageConverter}s depending on the 3rd party
* libraries available on the classpath.
* </ul>
*
*
* @see EnableWebMvc
* @see WebMvcConfigurer
* @see WebMvcConfigurerAdapter
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册