在上一篇文章中我们简单的分析了一下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。