在spring中所有的自定义命名空间(像mvc,context等)下的标签解析都是由BeanDefinitionParser接口的子类来完成的。那么就找到
标签的解析类,看看是如何解析的。
我们看到有多个AnnotationDrivenBeanDefinitionParser,他们是用来处理不同命名空间下的标签的,我们今天研究的是
标签,所以我们找到对应的实现类是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser
对于一个陌生的类,首先要先去看它的Javadoc:
* A {@link BeanDefinitionParser} that provides the configuration for the
* {@code } MVC namespace element.
* * This class registers the following {@link HandlerMapping}s:
*
* - {@link RequestMappingHandlerMapping}
* ordered at 0 for mapping requests to annotated controller methods.
*
- {@link BeanNameUrlHandlerMapping}
* ordered at 2 to map URL paths to controller bean names.
*
* * Note: Additional HandlerMappings may be registered
* as a result of using the {@code } or the
* {@code } MVC namespace elements.
* * This class registers the following {@link HandlerAdapter}s:
*
* - {@link RequestMappingHandlerAdapter}
* for processing requests with annotated controller methods.
*
- {@link HttpRequestHandlerAdapter}
* for processing requests with {@link HttpRequestHandler}s.
*
- {@link SimpleControllerHandlerAdapter}
* for processing requests with interface-based {@link Controller}s.
*
* * This class registers the following {@link HandlerExceptionResolver}s:
*
* - {@link ExceptionHandlerExceptionResolver} for handling exceptions
* through @{@link ExceptionHandler} methods.
*
- {@link ResponseStatusExceptionResolver} for exceptions annotated
* with @{@link ResponseStatus}.
*
- {@link DefaultHandlerExceptionResolver} for resolving known Spring
* exception types
*
* * This class registers an {@link org.springframework.util.AntPathMatcher}
* and a {@link org.springframework.web.util.UrlPathHelper} to be used by:
*
* - the {@link RequestMappingHandlerMapping},
*
- the {@link HandlerMapping} for ViewControllers
*
- and the {@link HandlerMapping} for serving resources
*
* Note that those beans can be configured by using the {@code path-matching} MVC namespace element.
* * Both the {@link RequestMappingHandlerAdapter} and the
* {@link ExceptionHandlerExceptionResolver} are configured with instances of
* the following by default:
*
* - A {@link ContentNegotiationManager}
*
- A {@link DefaultFormattingConversionService}
*
- A {@link org.springframework.validation.beanvalidation.LocalValidatorFactoryBean}
* if a JSR-303 implementation is available on the classpath
*
- A range of {@link HttpMessageConverter}s depending on what 3rd party
* libraries are available on the classpath.
*
该注释文档说明该解析器向容器中注入了如下组件:
HandlerMapping :请求映射
1、RequestMappingHandlerMapping
支持@RequestMapping注解
2、BeanNameUrlHandlerMapping
将controller类的名字映射为请求url
HandlerAdapter : 请求处理
1、RequestMappingHandlerAdapter
处理@Controller和@RequestMapping注解的处理器
2、HttpRequestHandlerAdapter
处理继承了HttpRequestHandler创建的处理器
3、SimpleControllerHandlerAdapter
处理继承自Controller接口的处理器
ExceptionResolver:处理异常的解析器
1、ExceptionHandlerExceptionResolver
2、ResponseStatusExceptionResolver
3、DefaultHandlerExceptionResolver
代码如下:
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
...
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
parserContext.popAndRegisterContainingComponent();
...
}
上面省略大量代码,这里只贴出部分注册组件的代码部分。
其中
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
这个将容器默认mapping和adapter加进来:
public static void registerDefaultComponents(ParserContext parserContext, Object source) {
registerBeanNameUrlHandlerMapping(parserContext, source);
registerHttpRequestHandlerAdapter(parserContext, source);
registerSimpleControllerHandlerAdapter(parserContext, source);
}
总结
这里来说说配置开启的两个常用的组件,RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
像其实
标签是告诉Spring容器来扫描指定包下的类,并注册被@Component,@Controller,@Service,@Repository等注解标记的组件相似。
是告知Spring容器,我们启用注解驱动,支持@RequestMapping注解,这样我们就可以使用@RequestMapping来配置处理器。