一、前沿
在 Spring MVC 的项目中,我们经常使用 <mvc:annotation-driven> 这个配置,那么这个配置到底是做什么的呢?下面来分析一下,首先找到 mvc 的命名空间的定义,如下图:
从上述图中可知,annotation-driven 配置的实现类应该是定义在了 MvcNamespaceHandler 类中,是不是这样的呢?下面我们看下 MvcNamespaceHandler 源码
二、MvcNamespaceHandler
MvcNamespaceHandler 源码如下:
/**
* {@link NamespaceHandler} for Spring MVC configuration namespace.
*
* @author Keith Donald
* @author Jeremy Grelle
* @author Sebastien Deleuze
* @since 3.0
*/
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// 注册 annotation-driven 标签的解析器 AnnotationDrivenBeanDefinitionParser,用来解析 Controller
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
// 注册 default-servlet-handler 标签的解析器 DefaultServletHandlerBeanDefinitionParser,用来解析静态资源文件(html、jsp、js和css等)
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
// 注册 interceptors 标签的解析器 InterceptorsBeanDefinitionParser,用来解析拦截器
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
// 注册 resources 标签的解析器 ResourcesBeanDefinitionParser,用来解析资源文件
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
// 注册 view-controller、redirect-view-controller、status-controller 标签的解析器 ViewControllerBeanDefinitionParser,用来解析视图view
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
// 注册 view-resolvers 标签的解析器 ViewResolversBeanDefinitionParser,用来解析视图解析器
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
// 注册 freemarker-configurer 标签的解析器 FreeMarkerConfigurerBeanDefinitionParser,用来解析 freemarker 配置
registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
// 注册 groovy-configurer 标签的解析器 GroovyMarkupConfigurerBeanDefinitionParser,用来解析 groovy 配置
registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
// 注册 script-template-configurer 标签的解析器 ScriptTemplateConfigurerBeanDefinitionParser,用来解析 script 脚本模板配置
registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
// 注册 cors 标签的解析器 CorsBeanDefinitionParser,用来解析跨域
registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
}
}
从上述源码中可知 annotation-driven 配置对应的解析类 AnnotationDrivenBeanDefinitionParser 确实是定义在 MvcNamespaceHandler 的 init 方法中,那么 annotation-driven 配置实现的具体业务肯定在 AnnotationDrivenBeanDefinitionParser 类中,下面我们分析一下 AnnotationDrivenBeanDefinitionParser 源码
三、AnnotationDrivenBeanDefinitionParser
AnnotationDrivenBeanDefinitionParser 的 parse 方法实现了具体的解析逻辑,源码如下:
/**
* A {@link BeanDefinitionParser} that provides the configuration for the
* {@code <annotation-driven/>} MVC namespace element.
*
* <p>This class registers the following {@link HandlerMapping HandlerMappings}:</p>
* <ul>
* <li>{@link RequestMappingHandlerMapping}
* 将请求映射到带注解的控制器方法时,按照0排序,例如 @RequestMapping("/test")
* ordered at 0 for mapping requests to annotated controller methods.
* <li>{@link BeanNameUrlHandlerMapping}
* 将URL路径映射到控制器bean名称时,按照2排序
* ordered at 2 to map URL paths to controller bean names.
* </ul>
*
* <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 HandlerAdapters}:
* <ul>
* <li>{@link RequestMappingHandlerAdapter}
* 处理带有@controller注解的适配器(支持自定义的参数和返回值),对应于 RequestMappingHandlerMapping,例如 @RequestMapping("/test")
* for processing requests with annotated controller methods.
* <li>{@link HttpRequestHandlerAdapter}
* 处理带有 HttpRequestHandlers 的适配器
* for processing requests with {@link HttpRequestHandler HttpRequestHandlers}.
* <li>{@link SimpleControllerHandlerAdapter}
* 处理基于 Controllers 接口的适配器
* for processing requests with interface-based {@link Controller Controllers}.
* </ul>
*
* 异常处理器
* <p>This class registers the following {@link HandlerExceptionResolver HandlerExceptionResolvers}:
* <ul>
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
* with {@link org.springframework.web.bind.annotation.ResponseStatus}.
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
* exception types
* </ul>
*
* <p>This class registers an {@link org.springframework.util.AntPathMatcher}
* and a {@link org.springframework.web.util.UrlPathHelper} to be used by:
* <ul>
* <li>the {@link RequestMappingHandlerMapping},
* <li>the {@link HandlerMapping} for ViewControllers
* <li>and the {@link HandlerMapping} for serving resources
* </ul>
* Note that those beans can be configured by using the {@code path-matching}
* MVC namespace element.
*
* <p>Both the {@link RequestMappingHandlerAdapter} and the
* {@link ExceptionHandlerExceptionResolver} are configured with instances of
* the following by default:
* <ul>
* <li>A {@link ContentNegotiationManager}
* <li>A {@link DefaultFormattingConversionService}
* <li>A {@link org.springframework.validation.beanvalidation.LocalValidatorFactoryBean}
* if a JSR-303 implementation is available on the classpath
* <li>A range of {@link HttpMessageConverter HttpMessageConverters} depending on which third-party
* libraries are available on the classpath.
* </ul>
*
* @author Keith Donald
* @author Juergen Hoeller
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Brian Clozel
* @author Agim Emruli
* @since 3.0
*/
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext context) {
Object source = context.extractSource(element);
XmlReaderContext readerContext = context.getReaderContext();
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
context.pushContainingComponent(compDefinition);
RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, context);
// 定义 RequestMappingHandlerMapping
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
handlerMappingDef.setSource(source);
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 排序值为 0
handlerMappingDef.getPropertyValues().add("order", 0);
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
if (element.hasAttribute("enable-matrix-variables")) {
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
}
configurePathMatchingProperties(handlerMappingDef, element, context);
// 注册 RequestMappingHandlerMapping 类型对应的 RootBeanDefinition
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);
RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, context, source);
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);
RuntimeBeanReference conversionService = getConversionService(element, source, context);
RuntimeBeanReference validator = getValidator(element, source, context);
RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);
RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
bindingDef.setSource(source);
bindingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
bindingDef.getPropertyValues().add("conversionService", conversionService);
bindingDef.getPropertyValues().add("validator", validator);
bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);
ManagedList<?> messageConverters = getMessageConverters(element, source, context);
ManagedList<?> argumentResolvers = getArgumentResolvers(element, context);
ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, context);
String asyncTimeout = getAsyncTimeout(element);
RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
ManagedList<?> callableInterceptors = getCallableInterceptors(element, source, context);
ManagedList<?> deferredResultInterceptors = getDeferredResultInterceptors(element, source, context);
// 定义 RequestMappingHandlerAdapter
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
// 消息转换器
handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
addRequestBodyAdvice(handlerAdapterDef);
addResponseBodyAdvice(handlerAdapterDef);
if (element.hasAttribute("ignore-default-model-on-redirect")) {
Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignore-default-model-on-redirect"));
handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
}
if (argumentResolvers != null) {
handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
}
if (returnValueHandlers != null) {
handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
}
if (asyncTimeout != null) {
handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
}
if (asyncExecutor != null) {
handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
}
handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
// 注册 RequestMappingHandlerAdapter 对应的 RootBeanDefinition
readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
RootBeanDefinition uriContributorDef =
new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
uriContributorDef.setSource(source);
uriContributorDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
uriContributorDef.getPropertyValues().addPropertyValue("conversionService", conversionService);
String uriContributorName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
readerContext.getRegistry().registerBeanDefinition(uriContributorName, uriContributorDef);
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
csInterceptorDef.setSource(source);
csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);
RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
mappedInterceptorDef.setSource(source);
mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedInterceptorDef);
// 定义 ExceptionHandlerExceptionResolver 异常处理器
RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
methodExceptionResolver.setSource(source);
methodExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
methodExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
methodExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
// 排序值为 0
methodExceptionResolver.getPropertyValues().add("order", 0);
addResponseBodyAdvice(methodExceptionResolver);
if (argumentResolvers != null) {
methodExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
}
if (returnValueHandlers != null) {
methodExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
}
String methodExResolverName = readerContext.registerWithGeneratedName(methodExceptionResolver);
// 定义 ResponseStatusExceptionResolver 返回状态异常解析器
RootBeanDefinition statusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
statusExceptionResolver.setSource(source);
statusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 排序值为 1
statusExceptionResolver.getPropertyValues().add("order", 1);
String statusExResolverName = readerContext.registerWithGeneratedName(statusExceptionResolver);
// 定义Spring中已知的异常解析器
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
defaultExceptionResolver.setSource(source);
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 排序值为 2
defaultExceptionResolver.getPropertyValues().add("order", 2);
String defaultExResolverName = readerContext.registerWithGeneratedName(defaultExceptionResolver);
// 将上面所有的 bean 组件注册到上下文中
context.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
context.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
context.registerComponent(new BeanComponentDefinition(uriContributorDef, uriContributorName));
context.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, mappedInterceptorName));
context.registerComponent(new BeanComponentDefinition(methodExceptionResolver, methodExResolverName));
context.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
context.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
// 注册默认的一些组件,例如 BeanNameUrlHandlerMapping、HttpRequestHandlerAdapter、
// SimpleControllerHandlerAdapter 和 HandlerMappingIntrospector
MvcNamespaceUtils.registerDefaultComponents(context, source);
context.popAndRegisterContainingComponent();
return null;
}
}
从上述源码中可以看出,在 AnnotationDrivenBeanDefinitionParser 中主要实现了注册了很多 bean 的功能,其中我们最关心的就是 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 两个类,功能分别如图:
RequestMappingHandlerMapping : HandlerMapping 的实现类,它处理的是 @RequestMapping 注解,并将其注册到映射表中,即 url 对应的 Controller 的 方法
RequestMappingHandlerAdapter : HandlerAdapter 的实现类,它是处理请求的适配器,就是确定调用哪个 Controller 的 哪个方法
到这里,AnnotationDrivenBeanDefinitionParser 的源码就分析完了,其中没有什么太多复杂的逻辑,代码注释都写清楚了
四、annotation-driven 作用
通过阅读 AnnotationDrivenBeanDefinitionParser 的源码可知,annotation-driven 配置的作用如下:
1)、主要是注册了 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter bean,存储了请求url到Controller方法的映射关系
2)、注册了异常处理器
五、总结
Spring MVC 中如果配置了 <mvc:annotation-driven> ,则所有的 Controller 就会被解析,所以相应的 .do 请求就会被 Controller 处理,因此这个配置至关重要。当请求没有匹配到处理类(其中包括没有配置 <mvc:annotation-driven> 或者 访问的是静态资源文件)时,就会去找 <mvc:default-servlet-handler> (处理静态资源文件)配置的 DefaultServletHttpRequestHandler 默认处理器处理了
今天的文章annotation-driven 配置详解分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/25097.html