@Nullable public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean){ // 获取Bean标签的ID属性 String id = ele.getAttribute(ID_ATTRIBUTE); // 获取Bean标签的Name属性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) { // 将name属性的值通过,; 进行分割 转为字符串数字(即在配置文件中如配置多个name 在此做处理) String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); }
String beanName = id;
// 如果ID为空 使用配置的第一个name属性作为ID if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { // 校验beanName和aliases的唯一性 // 内部核心为使用usedNames集合保存所有已经使用了的beanName和alisa checkNameUniqueness(beanName, aliases, ele); } // 进一步解析其他所有属性到GenericBeanDefinition对象中 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) { // 如果bean没有指定beanName 那么使用默认规则为此Bean生成beanName 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 && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); returnnull; } } String[] aliasesArray = StringUtils.toStringArray(aliases); // 将信息封装到BeanDefinitionHolder对象中 returnnew BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } returnnull; }
/** Map from alias to canonical name */ privatefinal Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
publicvoidregisterAlias(String name, String alias){ Assert.hasText(name, "'name' must not be empty"); Assert.hasText(alias, "'alias' must not be empty"); if (alias.equals(name)) { // 如果beanName与alias相同的话不记录alias 并删除对应的alias this.aliasMap.remove(alias); } else { String registeredName = this.aliasMap.get(alias); if (registeredName != null) { if (registeredName.equals(name)) { // 如果别名已经注册过并且指向的name和当前name相同 不做任何处理 return; } // 如果alias不允许被覆盖则抛出异常 if (!allowAliasOverriding()) { thrownew IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'."); } } // 校验循环指向依赖 如A->B B->C C->A则出错 checkForAliasCircle(name, alias); this.aliasMap.put(alias, name); } }
}
通过 checkForAliasCircle() 方法来检查 alias 循环依赖,当 A -> B 存在时,若再次出现 A -> C -> B 则会抛出异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
protectedvoidcheckForAliasCircle(String name, String alias){ if (hasAlias(alias, name)) { thrownew IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': Circular reference - '" + name + "' is a direct or indirect alias for '" + alias + "' already"); } }
protectedvoidprocessAliasRegistration(Element ele){ // 获取 alisa 标签 name 属性 String name = ele.getAttribute(NAME_ATTRIBUTE); // 获取 alisa 标签 alias 属性 String alias = ele.getAttribute(ALIAS_ATTRIBUTE); boolean valid = true; if (!StringUtils.hasText(name)) { getReaderContext().error("Name must not be empty", ele); valid = false; } if (!StringUtils.hasText(alias)) { getReaderContext().error("Alias must not be empty", ele); valid = false; } if (valid) { try { // 进行别名注册 getReaderContext().getRegistry().registerAlias(name, alias); } catch (Exception ex) { getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, ex); } // 别名注册后告知监听器做相应处理 getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); } }
}
首先对 alias 标签属性进行提取校验,校验通过后进行别名注册,别名注册和 bean 标签解析中的别名注册一直,此处不再赘述