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

可以看到所对应的就是默认标签 。 接着 , 我们进入parseDefaultElement方法:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {//import标签解析if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}//alias标签解析else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}//bean标签else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);} }这里面主要是对import、alias、bean标签的解析以及beans的字标签的递归解析 , 主要看看bean标签的解析:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {// 解析elment封装为BeanDefinitionHolder对象BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {// 该方法功能不重要 , 主要理解设计思想:装饰者设计模式以及SPI设计思想bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// 完成document到BeanDefinition对象转换后 , 对BeanDefinition对象进行缓存注册BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}// Send registration event.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));} }public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {// 获取id和name属性String id = ele.getAttribute(ID_ATTRIBUTE);String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);// 获取别名属性 , 多个别名可用,;隔开List aliases = new ArrayList<>();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进行装饰: