在上一篇文章中我们简单的分析了一下AnnotationDrivenBeanDefinitionParser,在这一篇的文章中我们继续分析AnnotationDrivenBeanDefinitionParser的内容。AnnotationDrivenBeanDefinitionParser这个类最最重要的一个方法就是parse方法。在这篇文章中我们简单的分析一下parse方法的内容。先看parse中的这一段代码:
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
handlerMappingDef.setSource(source);
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//基础建设类的角色
handlerMappingDef.getPropertyValues().add("order", 0);//order的顺序
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
if (element.hasAttribute("enable-matrix-variables")) {//是否支持Matrix variables变量。
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
}
else if (element.hasAttribute("enableMatrixVariables")) {
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enableMatrixVariables"));
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
}在上面的这一段代码中我们创建了一个RequestMappingHandlerMapping的BeanDefinition其实也相当于是默认配置了RequestMappingHandlerMapping。在这个BeanDefinition中我们设置了bean的role的值,order的顺序。同时还取了enable-matrix-variables这个属性的值。这个属性值是一个boolean类型,这个属性的作用是支持Matrix variables。通常在我们的URL中是会把带分号的数据移除掉的,如果我们配置了这个属性的值为true的话,就可以在URL的后面添加分号分割的数据。如:/test/name;userName=zhangsan这样。请求映射器的处理是需要在请求映射处理方法上添加@MatrixVariable注解,参数解析器为:MatrixVariableMethodArgumentResolver或MatrixVariableMapMethodArgumentResolver。有关Matrix variables更多的内容可以参考《看透springMvc源代码分析与实践》214页。我们下面接着分析:
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element,
ParserContext parserContext) {
/*
*获取path-matching的元素,配置形式大概如下
* <mvc:annotation-driven>
* <mvc:path-matching>
* </mvc:path-matching>
* </mvc:annotation-driven>
* 这个配置是个可选配置,用来配置请求路径匹配模式的
*/
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
if (pathMatchingElement != null) {
Object source = parserContext.extractSource(element);
if (pathMatchingElement.hasAttribute("suffix-pattern")) {
//如果suffix-pattern这个属性的话,则取这个属性值。这个属性值默认是:true
//这个属性值的作用是:是否配置.*这种模式
//例如我们在一个RequestMapping中配置的URL为:/listUserInfo,则/listUserInfo.json这样的请求也会被
//这个请求映射处理器方法所处理,即/listUserInfo相当于/listUserInfo.*
Boolean useSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("suffix-pattern"));
handlerMappingDef.getPropertyValues().add("useSuffixPatternMatch", useSuffixPatternMatch);
}
//这个属性值默认为true。 匹配/users的请求也匹配 /users/
if (pathMatchingElement.hasAttribute("trailing-slash")) {
Boolean useTrailingSlashMatch = Boolean.valueOf(pathMatchingElement.getAttribute("trailing-slash"));
handlerMappingDef.getPropertyValues().add("useTrailingSlashMatch", useTrailingSlashMatch);
}
//现在 后缀匹配模式 避免 . 这个字符引起的歧义
//默认为false
if (pathMatchingElement.hasAttribute("registered-suffixes-only")) {
Boolean useRegisteredSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("registered-suffixes-only"));
handlerMappingDef.getPropertyValues().add("useRegisteredSuffixPatternMatch", useRegisteredSuffixPatternMatch);
}
RuntimeBeanReference pathHelperRef = null;
//如果配置这个的话 需要继承UrlPathHelper这个类 寻找请求路径用的
//默认为UrlPathHelper
if (pathMatchingElement.hasAttribute("path-helper")) {
pathHelperRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-helper"));
}
pathHelperRef = MvcNamespaceUtils.registerUrlPathHelper(pathHelperRef, parserContext, source);
handlerMappingDef.getPropertyValues().add("urlPathHelper", pathHelperRef);
RuntimeBeanReference pathMatcherRef = null;
//路径匹配模式
//目前所使用的为AntPathMatcher。可以自定义
//Ant风格的URL。如:/user/*/createUser 匹配:/user/aaa/createUser、 /user/bbb/createUser
// /user/**/createUser 匹配 /user/createUser 、/user/aaa/bbb/createUser
// /user/{userId} 匹配 /user/123 、/user/1455
if (pathMatchingElement.hasAttribute("path-matcher")) {
pathMatcherRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-matcher"));
}
pathMatcherRef = MvcNamespaceUtils.registerPathMatcher(pathMatcherRef, parserContext, source);
handlerMappingDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
}
}
这一段逻辑主要是解析<mvc:path-matching>标签。我们接着往下看:
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
private RuntimeBeanReference getConversionService(Element element, Object source, ParserContext parserContext) {
RuntimeBeanReference conversionServiceRef;
//如果配置了conversion-service属性的值,则使用所指定的bean,这个bean必须是ConversionService的子类。
if (element.hasAttribute("conversion-service")) {
conversionServiceRef = new RuntimeBeanReference(element.getAttribute("conversion-service"));
}
else {
//如果没有配置如果配置了conversion-service属性的值,则使用默认的ConversionService
//这里使用的FormattingConversionServiceFactoryBean,但是这个类没有实现ConversionService这个接口,但是这个类
//实现了FactoryBean这个接口,在它的getObject方法中返回的是在afterPropertiesSet这个方法中创建的DefaultFormattingConversionService
//所以默认的ConversionService是DefaultFormattingConversionService这个类。
//在这个类中大概初始化了118个Converters
RootBeanDefinition conversionDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
conversionDef.setSource(source);
conversionDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String conversionName = parserContext.getReaderContext().registerWithGeneratedName(conversionDef);
parserContext.registerComponent(new BeanComponentDefinition(conversionDef, conversionName));
conversionServiceRef = new RuntimeBeanReference(conversionName);
}
return conversionServiceRef;
}
在上面的代码中进行了ConversionService的配置,默认配置了DefaultFormattingConversionService这个类型转换服务类。
RuntimeBeanReference validator = getValidator(element, source, parserContext);
private RuntimeBeanReference getValidator(Element element, Object source, ParserContext parserContext) {
if (element.hasAttribute("validator")) {
return new RuntimeBeanReference(element.getAttribute("validator"));
}
//如果类路径中有javax.validation.Validator这个类的话,则配置OptionalValidatorFactoryBean
//作为默认的校验器类 组合JSR-303 Validation规范和Spring Validator
else if (javaxValidationPresent) {
RootBeanDefinition validatorDef = new RootBeanDefinition(
"org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean");
validatorDef.setSource(source);
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName));
return new RuntimeBeanReference(validatorName);
}
else {
return null;
}
}在上面的代码中进行数据校验器的配置,默认配置了OptionalValidatorFactoryBean数据校验器。
RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);
private RuntimeBeanReference getMessageCodesResolver(Element element) {
//默认的信息转换器是:DefaultMessageCodesResolver
//用来转换校验失败信息。
if (element.hasAttribute("message-codes-resolver")) {
return new RuntimeBeanReference(element.getAttribute("message-codes-resolver"));
}
else {
return null;
}
}在上面的代码中进行MessageCode是Resolver的配置,默认配置的是DefaultMessageCodesResolver。
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);在上面的这段代码中默认配置了ConfigurableWebBindingInitializer这个bean,并设置了三个属性值conversionService、validator、messageCodesResolver。