该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读
Spring 版本:5.1.14.RELEASE
开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》这一篇文章
该系列其他文章请查看:《死磕 Spring 之 IoC 篇 - 文章导读》
BeanDefinition 的解析阶段(XML 文件)
上一篇文章《BeanDefinition 的加载阶段(XML 文件)》获取到 org.w3c.dom.Document 对象后,需要通过 DefaultBeanDefinitionDocumentReader 进行解析,解析出 XML 文件中定义的 BeanDefinition 并进行注册,先来回顾一下上一篇文章中的这段代码:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // <1> 创建 BeanDefinitionDocumentReader 对象
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // <2> 获取已注册的 BeanDefinition 数量
    int countBefore = getRegistry().getBeanDefinitionCount();
    // <3> 创建 XmlReaderContext 对象(读取 Resource 资源的上下文对象)
    // <4> 根据 Document、XmlReaderContext 解析出所有的 BeanDefinition 并注册
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // <5> 计算新注册的 BeanDefinition 数量
    return getRegistry().getBeanDefinitionCount() - countBefore;
}
本文开始分析第 4 步,BeanDefinition 的解析阶段,其中 BeanDefinitionDocumentReader 只有 DefaultBeanDefinitionDocumentReader 一个默认实现类
BeanDefinitionDocumentReader 接口
org.springframework.beans.factory.xml.BeanDefinitionDocumentReader,解析 DOM document 中的 BeanDefinition 并注册,代码如下:
public interface BeanDefinitionDocumentReader {
	/**
	 * Read bean definitions from the given DOM document and
	 * register them with the registry in the given reader context.
	 * @param doc the DOM document
	 * @param readerContext the current context of the reader
	 * (includes the target registry and the resource being parsed)
	 * @throws BeanDefinitionStoreException in case of parsing errors
	 */
	void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) throws BeanDefinitionStoreException;
}
DefaultBeanDefinitionDocumentReader
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader,Spring 默认的 BeanDefinitionDocumentReader 实现类,从 XML 文件中解析出 BeanDefinition 并注册
构造函数
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    /** bean */
	public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;
	public static final String NESTED_BEANS_ELEMENT = "beans";
	public static final String ALIAS_ELEMENT = "alias";
	public static final String NAME_ATTRIBUTE = "name";
	public static final String ALIAS_ATTRIBUTE = "alias";
	public static final String IMPORT_ELEMENT = "import";
	public static final String RESOURCE_ATTRIBUTE = "resource";
	public static final String PROFILE_ATTRIBUTE = "profile";
	@Nullable
	private XmlReaderContext readerContext;
	/**
	 * XML 文件的 BeanDefinition 解析器
	 */
	@Nullable
	private BeanDefinitionParserDelegate delegate;
}
上面定义了 XML 文件中常用的标签
1. registerBeanDefinitions 方法
registerBeanDefinitions(Document doc, XmlReaderContext readerContext) 方法,根据 Document、XmlReaderContext 解析出所有的 BeanDefinition 并注册,方法如下:
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    // 获得 XML Document Root Element
    // 执行注册 BeanDefinition
    doRegisterBeanDefinitions(doc.getDocumentElement());
}
/**
 * Register each bean definition within the given root {@code <beans/>} element.
 */
@SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
    // 记录老的 BeanDefinitionParserDelegate 对象,避免再次调用当前方法时解析出现问题(默认值可能不同)
    BeanDefinitionParserDelegate parent = this.delegate;
    // <1> 创建 BeanDefinitionParserDelegate 对象 `delegate`,并初始化默认值
    this.delegate = createDelegate(getReaderContext(), root, parent);
    // <2> 检查 <beans /> 根标签的命名空间是否为空,或者是 http://www.springframework.org/schema/beans
    if (this.delegate.isDefaultNamespace(root)) {
        // <2.1> 获取 `profile` 属性
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            // <2.2> 使用分隔符切分,可能有多个 `profile`
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            // We cannot use Profiles.of(...) since profile expressions are not supported
            // in XML config. See SPR-12458 for details.
            // <2.3> 根据 Spring Environment 进行校验,如果所有 `profile` 都无效,则不进行注册
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                            "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }
    // <3> 解析前处理
    preProcessXml(root);
    // <4> 解析出 XML Document 中的 BeanDefinition 并注册
    parseBeanDefinitions(root, this.delegate);
    // <5> 解析后处理
    postProcessXml(root);
    // 设置 delegate 回老的 BeanDefinitionParserDelegate 对象
    this.delegate = parent;
}
首先获取 XML Document 的最顶层的标签,也就是 <beans />,然后对其子标签进行解析,这里的过程大致如下:
- 创建 BeanDefinitionParserDelegate 对象 delegate,并初始化默认值
- 检查 <beans />根标签是否是默认命名空间(xmlns 属性,为空或者是http://www.springframework.org/schema/beans),是的话进行校验- 获取 profile属性,使用分隔符切分
- 根据 Spring Environment 进行校验,如果所有 profile都无效,则不进行注册
 
- 获取 
- 解析前处理,空方法,暂时忽略
- 解析出 XML Document 中的 BeanDefinition 并注册,调用 parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法
- 解析后处理,空方法,暂时忽略
2. parseBeanDefinitions 方法
parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) 方法,解析 XML Document 的最顶层的标签,解析出 BeanDefinition 并注册,方法如下:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // <1> 如果根节点使用默认命名空间,执行默认解析
    if (delegate.isDefaultNamespace(root)) {
        // <1.1> 遍历所有的子节点
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                // <1.2> 如果该节点使用默认命名空间,执行默认解析
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);
                }
                // <1.3> 如果该节点非默认命名空间,执行自定义解析
                else {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    // <2> 如果根节点非默认命名空间,执行自定义解析
    else {
        delegate.parseCustomElement(root);
    }
}
解析过程大致如下:
- 如果根节点使用默认命名空间,执行默认解析
- 遍历所有的子节点
- 如果该节点使用默认命名空间,执行默认解析,调用 parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)方法
- 如果该节点非默认命名空间,执行自定义解析,调用 BeanDefinitionParserDelegate#parseCustomElement(Element ele)方法
 
- 如果根节点非默认命名空间,执行自定义解析,调用 BeanDefinitionParserDelegate#parseCustomElement(Element ele)方法
命名空间是什么?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
	<context:component-scan base-package="org.geekbang.thinking.in.spring.ioc.overview" />
    <bean id="user" class="org.geekbang.thinking.in.spring.ioc.overview.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="小马哥"/>
    </bean>
</beans>
在 XML 文件中的标签的 xmlns 可以定义默认的命名空间,xmlns:context 定义 context 的命名空间,xsi:schemaLocation 定义了命名空间对应的 XSD 文件(校验 XML 内容)。
上面的 <beans /> 和 <bean> 标签的命名空间为 http://www.springframework.org/schema/beans,其中 <context:component-scan /> 标签的命名空间为 http://www.springframework.org/schema/context(不是默认命名空间)
本文主要分析默认命名空间的解析过程,其他命名空间(注解相关)在后面进行分析,基于 Extensible XML authoring 扩展 Spring XML 元素会进入这里,主要是通过 NamespaceHandler 这个接口实现的。例如 Spring 集成 Mybatis 项目中的 <mybatis:scan /> 就是扩展  Spring XML 元素,具体实现在后面分析;Spring 的<context:component-scan /> 最终会通过 ComponentScanBeanDefinitionParser 进行解析。ComponentScanBeanDefinitionParser 是将 @Component 注解标注的类转换成 BeanDefinition 的解析器。
3. parseDefaultElement 方法
parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) 方法,处理默认命名空间的节点,方法如下:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        // 解析 `<import />`
        importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        // 解析 `<alias />`,将 name 对应的 alias 别名进行注册
        processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        // 解析 `<bean />`
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // 循环处理,解析 `<beans />`
        doRegisterBeanDefinitions(ele);
    }
}
解析下面四种标签:
- 
<import />标签,例如这么配置:<import resource="dependency-lookup-context.xml"/>,那么这里会获取到对应的 XML 文件,然后进行相同的处理过程
- 
<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的唯一性
 
- 获取标签的 
- 解析 <bean />标签相关属性,构造出一个 GenericBeanDefinition 对象,调用parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean)方法
- 如果不存在 beanName,则根据 Class 对象的名称生成一个
- 创建 BeanDefinitionHolder 对象,设置 beanName名称和aliases别名集合,返回
6. parseBeanDefinitionElement 重载方法
parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) 方法,解析 <bean /> 成 GenericBeanDefinition 对象,方法如下:
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    this.parseState.push(new BeanEntry(beanName));
    // <1> 获取 `class` 和 `parent` 属性
    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 {
        // <2> 构建一个 GenericBeanDefinition 对象 `bd`
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);
        // <3> 解析 `<bean />` 的各种属性并赋值
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        // 提取 description
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
        // <4> 解析 `<bean />` 的子标签,生成的对象设置到 `bd` 中
        // <4.1> 解析 `<meta />` 元数据标签
        parseMetaElements(ele, bd);
        // <4.2> 解析 `<lookup-method />` 标签
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        // <4.3> 解析 `<replaced-method />` 标签
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        // <4.4> 解析 `<constructor-arg />` 构造函数的参数集合标签
        parseConstructorArgElements(ele, bd);
        // <4.5> 解析 `<property />` 属性标签
        parsePropertyElements(ele, bd);
        // <4.5> 解析 `<qualifier />` 标签
        parseQualifierElements(ele, bd);
        // <5> 设置 Bean 的 `resource` 资源为 XML 文件资源
        bd.setResource(this.readerContext.getResource());
        // <6> 设置 Bean 的 `source` 来源为 `<bean />` 标签对象
        bd.setSource(extractSource(ele));
        return bd;
    }
    // ... 省略 catch 各种异常
    finally {
        this.parseState.pop();
    }
    return null;
}
过程如下:
- 获取 class和parent属性
- 构建一个 GenericBeanDefinition 对象 bd,设置parentName和beanClass(Class 对象)或者className(Class 名称)
- 解析 <bean />的各种属性并赋值:scope、abstract、lazy-init、autowire、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method
- 解析 <bean />的子标签,生成的对象设置到bd中- 解析 <meta />元数据标签,将 key-value 保存至 Map 中
- 解析 <lookup-method />标签,解析成 LookupOverride 对象,用于实现 Bean 中的某个方法
- 解析 <replaced-method />标签,解析成 ReplaceOverride 对象,用于替换 Bean 中的某个方法
- 解析 <constructor-arg />构造函数的参数集合标签,将各个参数解析出来,可根据 index 属性进行排序
- 解析 <property />属性标签,将各个属性解析出来,每个属性对应一个 PropertyValue,添加至bd的 MutablePropertyValues 属性中
- 解析 <qualifier />标签,解析出需要注入的对象 AutowireCandidateQualifier
 
- 解析 
- 设置 Bean 的 resource资源为 XML 文件资源
- 设置 Bean 的 source来源为<bean />标签对象
lookup-method,会被解析成 LookupOverride 对象,replaced-method 会被解析成 ReplaceOverride 对象,这两个标签不是很常用
lookup-method:例如一个在一个抽象类中定义了抽象方法,可以通过这个标签定义一个 Bean 实现这个方法,Spring 会动态改变抽象类该方法的实现
replace-method:通过这个标签定义一个 Bean,去覆盖对应的方法,Spring 会动态替换类的这个方法
BeanDefinitionReaderUtils
org.springframework.beans.factory.support.BeanDefinitionReaderUtils,BeanDefinition 的解析过程中的工具类
7. registerBeanDefinition 方法
registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry),注册 BeanDefinition,方法如下:
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {
    // <1> 注册 BeanDefinition
    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    // <2> 注册 alias 别名
    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}
过程如下:
- 注册 BeanDefinition,调用 BeanDefinitionRegistry#registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法
- 注册 alias 别名,调用 BeanDefinitionRegistry#registerAlias(String name, String alias)方法
这里的 BeanDefinitionRegistry 实现类是 DefaultListableBeanFactory,它是 Spring 底层 IoC 容器,还继承了 SimpleAliasRegistry(AliasRegistry 实现类)
8. 注册 BeanDefinition
// org.springframework.beans.factory.support.DefaultListableBeanFactory
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {
    // 校验 beanName 与 beanDefinition 非空
    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    // <1> 校验 BeanDefinition
    // 这是注册前的最后一次校验了,主要是对属性 methodOverrides 进行校验
    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }
    // <2> 从缓存中获取指定 beanName 的 BeanDefinition
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    // <3> 如果已经存在
    if (existingDefinition != null) {
        // 如果存在但是不允许覆盖,抛出异常
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }
        // 覆盖 beanDefinition 大于 被覆盖的 beanDefinition 的 ROLE ,打印 info 日志
        else if (existingDefinition.getRole() < beanDefinition.getRole()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (logger.isInfoEnabled()) {
                logger.info("Overriding user-defined bean definition for bean '" + beanName +
                        "' with a framework-generated bean definition: replacing [" +
                        existingDefinition + "] with [" + beanDefinition + "]");
            }
        }
        // 覆盖 beanDefinition 与 被覆盖的 beanDefinition 不相同,打印 debug 日志
        else if (!beanDefinition.equals(existingDefinition)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Overriding bean definition for bean '" + beanName +
                        "' with a different definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        // 其它,打印 debug 日志
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Overriding bean definition for bean '" + beanName +
                        "' with an equivalent definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    // <4> 如果未存在
    else {
        // 检测创建 Bean 阶段是否已经开启,如果开启了则需要对 beanDefinitionMap 进行并发控制
        if (hasBeanCreationStarted()) {
            // beanDefinitionMap 为全局变量,避免并发情况
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                // 添加到 BeanDefinition 到 beanDefinitionMap 中
                this.beanDefinitionMap.put(beanName, beanDefinition);
                // 添加 beanName 到 beanDefinitionNames 中
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                // 从 manualSingletonNames 移除 beanName
                removeManualSingletonName(beanName);
            }
        }
        else {
            // 添加到 BeanDefinition 到 beanDefinitionMap 中
            // Still in startup registration phase
            this.beanDefinitionMap.put(beanName, beanDefinition);
            // 添加 beanName 到 beanDefinitionNames 中,保证注册顺序
            this.beanDefinitionNames.add(beanName);
            // 从 manualSingletonNames 移除 beanName
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
    // <5> 重新设置 beanName 对应的缓存
    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}
逻辑不复杂,主要是对 beanName 和该 BeanDefinition 对象的校验,最终将其映射保存在 beanDefinitionMap 中(ConcurrentHashMap),key 就是 beanName
9. 注册 alias 别名
// org.springframework.core.SimpleAliasRegistry
@Override
public void registerAlias(String name, String alias) {
   // 校验 name 、 alias
   Assert.hasText(name, "'name' must not be empty");
   Assert.hasText(alias, "'alias' must not be empty");
   synchronized (this.aliasMap) {
      // name == alias 则去掉alias
      if (alias.equals(name)) {
         this.aliasMap.remove(alias);
         if (logger.isDebugEnabled()) {
            logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
         }
      }
      else {
         // 获取 alias 已注册的 beanName
         String registeredName = this.aliasMap.get(alias);
         // 已存在
         if (registeredName != null) {
            // 相同,则 return ,无需重复注册
            if (registeredName.equals(name)) {
               // An existing alias - no need to re-register
               return;
            }
            // 不允许覆盖,则抛出 IllegalStateException 异常
            if (!allowAliasOverriding()) {
               throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
                     name + "': It is already registered for name '" + registeredName + "'.");
            }
            if (logger.isDebugEnabled()) {
               logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
                     registeredName + "' with new target name '" + name + "'");
            }
         }
         // 校验,是否存在循环指向
         checkForAliasCircle(name, alias);
         // 注册 alias
         this.aliasMap.put(alias, name);
         if (logger.isTraceEnabled()) {
            logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
         }
      }
   }
}
逻辑不复杂,将 alias 与 beanName 映射保存至 aliasMap 中(ConcurrentHashMap)
总结
解析出 XML 文件中的 BeanDefinition 并注册的整个过程大致如下:
- 根据 XSD 文件对 XML 文件进行校验
- 将 XML 文件资源转换成 org.w3c.dom.Document对象
- 根据 Document 对象解析 <beans />标签,遍历所有的子标签- 如果是子标签是默认的命名空间(为空或者 http://www.springframework.org/schema/beans)则进行处理,例如:<import>、<alias />、<bean />和<beans />,其中<bean />会被解析出一个 GenericBeanDefinition 对象,然后进行注册
- 否则,找到对应的 NamespaceHandler 对象进行解析,例如:<context:component-scan />、<context:annotation-config />、<util:list />,这些非默认命名空间的标签都会有对应的 BeanDefinitionParser 解析器
 
- 如果是子标签是默认的命名空间(为空或者 
至此,我们通过 XML 文件定义的 Bean 已经转换成了 Bean 的“前身”,也就是 BeanDefinition 对象。接下来会分析在 XML 文件中,非默认命名空间的标签是如何进行处理的。