Spring的XML解析原理,这一次全搞懂再走( 六 )

<>();if (StringUtils.hasLength(nameAttr)) {String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);aliases.addAll(Arrays.asList(nameArr));}String beanName = id;if (!StringUtils.hasText(beanName)if (logger.isTraceEnabled()) {logger.trace("No XML 'id' specified - using '" + beanName +"' as bean name and " + aliases + " as aliases");}}//检查beanName是否重复if (containingBean == null) {checkNameUniqueness(beanName, aliases, ele);}// 具体的解析封装过程还在这个方法里AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);if (beanDefinition != null) {if (!StringUtils.hasText(beanName)) {try {if (containingBean != null) {beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);} else {beanName = this.readerContext.generateBeanName(beanDefinition);// Register an alias for the plain bean class name, if still possible,// if the generator returned the class name plus a suffix.// This is expected for Spring 1.2/2.0 backwards compatibility.String beanClassName = beanDefinition.getBeanClassName();if (beanClassName != null}}if (logger.isTraceEnabled()) {logger.trace("Neither XML 'id' nor 'name' specified - " +"using generated bean name [" + beanName + "]");}} catch (Exception ex) {error(ex.getMessage(), ele);return null;}}String[] aliasesArray = StringUtils.toStringArray(aliases);return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);}return null; } // bean的解析 public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {this.parseState.push(new BeanEntry(beanName));// 获取class名称和父类名称String className = null;if (ele.hasAttribute(CLASS_ATTRIBUTE)) {className = ele.getAttribute(CLASS_ATTRIBUTE).trim();}String parent = null;if (ele.hasAttribute(PARENT_ATTRIBUTE)) {parent = ele.getAttribute(PARENT_ATTRIBUTE);}try {// 创建GenericBeanDefinition对象AbstractBeanDefinition bd = createBeanDefinition(className, parent);// 解析bean标签的属性 , 并把解析出来的属性设置到BeanDefinition对象中parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));//解析bean中的meta标签parseMetaElements(ele, bd);//解析bean中的lookup-method标签parseLookupOverrideSubElements(ele, bd.getMethodOverrides());//解析bean中的replaced-method标签parseReplacedMethodSubElements(ele, bd.getMethodOverrides());//解析bean中的constructor-arg标签parseConstructorArgElements(ele, bd);//解析bean中的property标签parsePropertyElements(ele, bd);parseQualifierElements(ele, bd);bd.setResource(this.readerContext.getResource());bd.setSource(extractSource(ele));return bd;}return null; }bean标签的解析步骤仔细理解并不复杂 , 就是将一个个标签属性的值装入到了BeanDefinition对象中 , 这里需要注意parseConstructorArgElements和parsePropertyElements方法 , 分别是对constructor-arg和property标签的解析 , 解析完成后分别装入了BeanDefinition对象的constructorArgumentValues和propertyValues中 , 而这两个属性在接下来c和p标签的解析中还会用到 , 而且还涉及一个很重要的设计思想——装饰器模式 。 Bean标签解析完成后将生成的BeanDefinition对象、bean的名称以及别名一起封装到了BeanDefinitionHolder对象并返回 , 然后调用了decorateBeanDefinitionIfRequired进行装饰: