死磕Spring之IoC篇 - BeanDefinition 的解析阶段(XML 文件) (3)

<alias /> 标签,将 name 对应的 alias 别名进行注册,往 AliasRegistry 注册(BeanDefinitionRegistry 继承了它),也就是说你可以通过别名找到对应的 Bean

<bean /> 标签,解析成 BeanDefinition 并注册,调用 processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) 方法

<beans /> 标签,循环处理,和前面的步骤相同

4. processBeanDefinition 方法

processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) 方法,将 <bean /> 标签解析成 BeanDefinition 并注册,方法如下:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // <1> 解析 `<bean />` 标签,返回 BeanDefinitionHolder 对象(包含 BeanDefinition、beanName、aliases) BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { // <2> 对该标签进行装饰,一般不会,暂时忽略 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. // <3> 进行 BeanDefinition 的注册 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. // <4> 发出响应事件,通知相关的监听器,已完成该 Bean 标签的解析 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }

过程如下:

解析 <bean /> 标签,返回 BeanDefinitionHolder 对象(包含 BeanDefinition、beanName、aliases),调用 BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element ele) 方法

对该标签进行装饰,和上面处理自定义标签类似,暂时忽略

进行 BeanDefinition 的注册

发出响应事件,通知相关的监听器,已完成该 Bean 标签的解析

BeanDefinitionParserDelegate

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate,解析 XML Document 里面的 BeanDefinition

5. parseBeanDefinitionElement 方法

parseBeanDefinitionElement(Element ele) 方法,将 XML Document 里面的某个标签解析成 BeanDefinition,方法如下:

@Nullable public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { // <1> 计算 BeanDefinition 的 `beanName` 名称和 `aliases` 别名集合 // <1.1> 获取标签的 `id` 和 `name` 属性 String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // <1.2> 将 `name` 属性全部添加至别名集合 List<String> aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } // <1.3> 设置 Bean 的名称,优先 `id` 属性,其次 `name` 属性 String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); // 移除出别名集合 if (logger.isTraceEnabled()) { logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } // <1.4> 检查 `beanName` 的唯一性 if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } // <2> 解析 `<bean />` 标签相关属性,构造出一个 GenericBeanDefinition 对象 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { // <3> 如果不存在 `beanName`,则根据 Class 对象的名称生成一个 if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { // 内部 Bean // <3.1> 生成唯一的 `beanName` beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { // <3.2> 生成唯一的 beanName 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.isTraceEnabled()) { logger.trace("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } // <4> 创建 BeanDefinitionHolder 对象,设置 `beanName` 名称和 `aliases` 别名集合,返回 String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }

过程如下:

计算 BeanDefinition 的 beanName 名称和 aliases 别名集合

获取标签的 id 和 name 属性

将 name 属性全部添加至别名集合 aliases

设置 Bean 的名称 beanName,优先 id 属性,其次 name 属性

检查 beanName 的唯一性

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygpww.html