loadBeanDefinitions方法源码跟踪(二)
阅读原文时间:2021年04月20日阅读:1

因为字数超过了限制,所以分成了三篇,承接上篇:

https://www.jianshu.com/p/a0cfaedf3fc5

代码过宽,可以shift + 鼠标滚轮 左右滑动查看

先跟踪一个bean标签,下面是对应的配置文件

<!--配置mapper.java扫描-->
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="cn.mrdear.mapper"/>
    <property name="properties">
        <value>
            mappers=tk.mybatis.mapper.common.Mapper
        </value>
    </property>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

因为是bean标签,走的默认的名称空间方法,所以走这个标签的方法:

//3.如果该标签属于beans的名称空间,则进入这个方法
//xmlns="http://www.springframework.org/schema/beans"
parseDefaultElement(ele, delegate);

这个方法的实现在DefaultBeanDefinitionDocumentReader类中,因为标签下有多个子标签,所以每个子标签对应着一个方法

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);
    }

    //又嵌套一层<beans>标签进入这个方法
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {

        // recurse
        // 如果是嵌套的beans,那么就会重新调用标记2中的一个方法进行递归
        doRegisterBeanDefinitions(ele);
    }
}

/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*
* 处理bean元素,解析成bean definition并注册到工厂中
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {

    //3.1通过代理解析bean元素
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {

        //3.2如果有要求的话渲染beanDefinition
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {

            // Register the final decorated instance.
            //3.3注册最终被渲染的实例到工厂中
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
        }

        // Send registration event.
        // 发送注册事件
        // 这里是空实现
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

3.1 parseBeanDefinitionElement

跟踪3.1标记的方法

进入BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法

//3.1通过代理解析bean元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

/**
* Parses the supplied {@code <bean>} element. May return {@code null}
* if there were errors during parse. Errors are reported to the
* {@link org.springframework.beans.factory.parsing.ProblemReporter}.
*
* 解析bean元素。如果解析过程中发生错误则返回空
*/
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return parseBeanDefinitionElement(ele, null);
}

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {

    //拿bean标签上的id
    String id = ele.getAttribute(ID_ATTRIBUTE);

    //拿bean标签上的name属性
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    List<String> aliases = new ArrayList<String>();

    //有name属性进入
    if (StringUtils.hasLength(nameAttr)) {

        //name属性对应的name值如果有分隔符",; ",那么切分成数组
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);

        //这些name值就是别名
        aliases.addAll(Arrays.asList(nameArr));
    }

    //指定了id就用id值作为bean名称
    String beanName = id;

    //如果没有id,但是指定了name,就用name值作为bean名称
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {

        //拿第一个name值作为bean名称,其余的还是别名
        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) {

        //检查bean名称和别名是否已经被使用了,如果用了就报错
        //同时把这个bean的名称和别名加入代理的usedNames属性中
        //private final Set<String> usedNames = new HashSet<String>();
        checkNameUniqueness(beanName, aliases, ele);
    }

    //直接进入这个方法
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {

        //既没有指定id,也没有指定name就走这里面
        if (!StringUtils.hasText(beanName)) {
            try {

                //前面containingBean传递时为null,这里不走这个方法
                if (containingBean != null) {
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                        beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {

                    //生成一个bean名称,beanName
                    //如果这个bean是内部bean,全限定名后加#号再加哈希值
                    //如果是顶层bean,那么后面加#号再从0开始加数字,id已被注册数字就增1,直到唯一
                    //比如:tk.mybatis.spring.mapper.MapperScannerConfigurer#0
                    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)) {

                        //如果该类名没有被使用,那么注册该类名作为别名,比如:
                        //tk.mybatis.spring.mapper.MapperScannerConfigurer作为
                        //tk.mybatis.spring.mapper.MapperScannerConfigurer#0的别名
                        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);
                return null;
            }
        }
        String[] aliasesArray = StringUtils.toStringArray(aliases);

        //返回beanDefinition的持有者
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}

/**
* Parse the bean definition itself, without regard to name or aliases. May return
* {@code null} if problems occurred during the parsing of the bean definition.
*
* 不关注名称和别名,只解析bean definition自身
*/
public AbstractBeanDefinition parseBeanDefinitionElement(
    Element ele, String beanName, BeanDefinition containingBean) {

    //解析的时候放入,解析完成弹出,这里放入bean标签,
    //如果还嵌套有子标签,则后续放入子标签
    //子标签先弹出
    this.parseState.push(new BeanEntry(beanName));

    String className = null;
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {

        //如果有指定class属性,则拿到class属性值
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }

    try {
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {

            //如果有指定parent属性,则拿到parent属性值
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }

        //3.1.1创建BeanDefinition并设置两属性
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);

        //3.1.2将bean标签上的属性设置到bean definition中
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

        //如果bean标签下有子标签为description,拿到标签中的文本,设置到bean definition中
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

        //如果bean标签下有子标签为meta,拿到他的key和value属性,设置到bean definition中
        parseMetaElements(ele, bd);

        //如果bean标签下有子标签为lookup-method,拿到他的name和bean属性,设置到bean definition中
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

        //如果bean标签下有子标签为replaced-method,设置bean definition
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

        //如果bean标签下有子标签为constructor-arg,设置bean definition的构造方式
        parseConstructorArgElements(ele, bd);

        //这个标签比较常用,为Property标签
        //3.1.3解析Property的属性设置到bean definition中
        parsePropertyElements(ele, bd);

        //有qualifier子标签才走这个方法
        parseQualifierElements(ele, bd);

        //设置资源
        bd.setResource(this.readerContext.getResource());

        //这里为null
        bd.setSource(extractSource(ele));

        return bd;
    }
    catch (ClassNotFoundException ex) {
        error("Bean class [" + className + "] not found", ele, ex);
    }
    catch (NoClassDefFoundError err) {
        error("Class that bean class [" + className + "] depends on not found", ele, err);
    }
    catch (Throwable ex) {
        error("Unexpected failure during bean definition parsing", ele, ex);
    }
    finally {

        //解析的时候放入,解析完成弹出
        this.parseState.pop();
    }

    return null;
}

3.1.1 createBeanDefinition

跟踪标记3.1.1

//3.1.1创建BeanDefinition并设置两属性
AbstractBeanDefinition bd = createBeanDefinition(className, parent);

/**
* Create a bean definition for the given class name and parent name.
*
* 通过给定的className和parentName创建beanDefinition
*/
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
    throws ClassNotFoundException {

    return BeanDefinitionReaderUtils.createBeanDefinition(
        parentName, className, this.readerContext.getBeanClassLoader());
}

/**
* 此方法是BeanDefinitionReaderUtils的静态方法
*
* Create a new GenericBeanDefinition for the given parent name and class name,
* eagerly loading the bean class if a ClassLoader has been specified.
*
* 通过给定的parentName和className穿件一个新的GenericBeanDefinition
* 如果指定了ClassLoader,就提前加载bean class
*/
public static AbstractBeanDefinition createBeanDefinition(
    String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {

    GenericBeanDefinition bd = new GenericBeanDefinition();
    bd.setParentName(parentName);
    if (className != null) {
        if (classLoader != null) {

            //接受的属性是Object类型
            bd.setBeanClass(ClassUtils.forName(className, classLoader));
        }
        else {

            //接受的属性是Object类型
            bd.setBeanClassName(className);
        }
    }
    return bd;
}

3.1.2 parseBeanDefinitionAttributes

跟踪标记方法3.1.2

此方法在BeanDefinitionParserDelegate类中

//3.1.2将bean标签上的属性设置到bean definition中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

/**
* Apply the attributes of the given bean element to the given bean * definition.
*
* 将bean标签上的属性设置到bean definition中
*/
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
                                                            BeanDefinition containingBean, AbstractBeanDefinition bd) {

    //bean标签上已经没有singleton属性了,用scope代替,所以出现就报错
    if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
        error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
    }

    //如果设置了scope就拿其值
    else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
        bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
    }

    //此处containingBean为空
    else if (containingBean != null) {

        // Take default from containing bean in case of an inner bean definition.
        // 如果是一个内部的bean definition,用包含的bean的default
        bd.setScope(containingBean.getScope());
    }

    //是否有abstract属性
    if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
        bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    }

    String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);

    //lazyInit如果没有设置则为默认值,默认值用的代理类中defaults属性,
    //也就是this.defaults
    if (DEFAULT_VALUE.equals(lazyInit)) {
        lazyInit = this.defaults.getLazyInit();
    }

    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

    //默认值用的代理类中defaults属性,不进行autowire
    String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
    bd.setAutowireMode(getAutowireMode(autowire));

    //默认不进行依赖检查
    String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
    bd.setDependencyCheck(getDependencyCheck(dependencyCheck));

    //是否有depends-on属性
    if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
        String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
        bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
    }

    //是否有autowire-candidate属性,没有或者为默认则不设置
    String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
    if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
        String candidatePattern = this.defaults.getAutowireCandidates();
        if (candidatePattern != null) {
            String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
            bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
        }
    }
    else {
        bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
    }

    //是否有primary属性
    if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
        bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
    }

    //是否有init-method属性
    if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
        String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
        if (!"".equals(initMethodName)) {
            bd.setInitMethodName(initMethodName);
        }
    }
    else {

        //没有init-method属性,就拿代理类defaults属性的
        if (this.defaults.getInitMethod() != null) {
            bd.setInitMethodName(this.defaults.getInitMethod());
            bd.setEnforceInitMethod(false);
        }
    }

    //是否有destroy-method属性
    if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
        String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
        bd.setDestroyMethodName(destroyMethodName);
    }
    else {

        //没有destroy-method属性,就拿代理类defaults属性的
        if (this.defaults.getDestroyMethod() != null) {
            bd.setDestroyMethodName(this.defaults.getDestroyMethod());
            bd.setEnforceDestroyMethod(false);
        }
    }

    //是否有factory-method属性
    if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
        bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
    }

    //是否有factory-bean属性
    if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
        bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
    }

    return bd;
}

这样,bean标签上的属性也就解析完成了,对其属性的描述不管设置了还是没有设置的,都有相应的值对应到bean definition中。接下来就要解析,bean标签下的子标签了。

3.1.3 parsePropertyElements

跟踪3.1.3标记的方法

此方法在BeanDefinitionParserDelegate类中实现

//3.1.3解析Property的属性设置到bean definition中
parsePropertyElements(ele, bd);

/**
* Parse property sub-elements of the given bean element.
* 解析bean标签下property子标签
*/
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    NodeList nl = beanEle.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {

            //标签名为property才能进入,进入这个方法
            parsePropertyElement((Element) node, bd);
        }
    }
}

/**
* Parse a property element.
*/
public void parsePropertyElement(Element ele, BeanDefinition bd) {

    //拿到property标签的name属性
    String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
    if (!StringUtils.hasLength(propertyName)) {
        error("Tag 'property' must have a 'name' attribute", ele);
        return;
    }

    //解析的时候放入,解析完成弹出,这里放入property标签,
    //这里面还存有bean父标签,子标签解析完成后先弹出
    this.parseState.push(new PropertyEntry(propertyName));
    try {

        //bean标签下可以有多个property,但是不能重复name属性
        if (bd.getPropertyValues().contains(propertyName)) {
            error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
            return;
        }

        //进入这个方法,查看是怎么解析property标签属性的
        Object val = parsePropertyValue(ele, bd, propertyName);

        //将name属性和对应的value放入
        PropertyValue pv = new PropertyValue(propertyName, val);

        //解析property标签的子标签meta,
        //拿到meta的key和value属性,设置到PropertyValue中
        parseMetaElements(ele, pv);

        //这里没有实现,为null
        pv.setSource(extractSource(ele));

        //将PropertyValue添加到bean definition中
        bd.getPropertyValues().addPropertyValue(pv);
    }
    finally {

        //解析的时候放入,解析完成弹出,这里放入property标签
        this.parseState.pop();
    }
}

/**
* Get the value of a property element. May be a list etc.
* Also used for constructor arguments, "propertyName" being null in this case.
*
* 拿到property标签的value值,可能是list
* 也被constructor标签使用,这种情况propertyName为null
*/
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {

    //如果propertyName为null,则是constructor-arg标签
    //否则为property标签
    String elementName = (propertyName != null) ?
        "<property> element for property '" + propertyName + "'" :
    "<constructor-arg> element";

    // Should only have one child element: ref, value, list, etc.
    //不管是哪种标签,下面都应该只有一个子标签: ref, value, list等.
    NodeList nl = ele.getChildNodes();
    Element subElement = null;
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
            !nodeNameEquals(node, META_ELEMENT)) {

            // Child element is what we're looking for.
            //除开description和meta标签,子标签最多只能有一个
            if (subElement != null) {
                error(elementName + " must not contain more than one sub-element", ele);
            }
            else {
                subElement = (Element) node;
            }
        }
    }

    //看标签属性用的是value还是ref
    boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
    boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);

    //value和ref属性不能同时存在,如果有子标签,则value和ref都不能存在,否则报错
    if ((hasRefAttribute && hasValueAttribute) ||
        ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
        error(elementName +
              " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
    }

    //用的ref的情况
    if (hasRefAttribute) {
        String refName = ele.getAttribute(REF_ATTRIBUTE);
        if (!StringUtils.hasText(refName)) {
            error(elementName + " contains empty 'ref' attribute", ele);
        }
        RuntimeBeanReference ref = new RuntimeBeanReference(refName);
        ref.setSource(extractSource(ele));
        return ref;
    }

    //用的value的情况
    else if (hasValueAttribute) {
        TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
        valueHolder.setSource(extractSource(ele));
        return valueHolder;
    }

    //子标签不为null的情况,进入这个方法查看
    else if (subElement != null) {
        return parsePropertySubElement(subElement, bd);
    }
    else {

        // Neither child element nor "ref" or "value" attribute found.
        //没指定ref或者value或者子标签,返回null
        error(elementName + " must specify a ref or value", ele);
        return null;
    }
}

/**
* 这个方法还是在BeanDefinitionParserDelegate中
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
    return parsePropertySubElement(ele, bd, null);
}

/**
* Parse a value, ref or collection sub-element of a property or
* constructor-arg element.
*
* 解析property或者constructor-arg标签的子标签,可能为value, ref或者集合
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {

    //如果这个子标签不属于beans的名称空间,则走这个方法
    if (!isDefaultNamespace(ele)) {
        return parseNestedCustomElement(ele, bd);
    }

    //如果是bean子标签,则走这个方法
    else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
        BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
        if (nestedBd != null) {
            nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
        }
        return nestedBd;
    }

    //如果是ref子标签,则走这个方法
    else if (nodeNameEquals(ele, REF_ELEMENT)) {

        // A generic reference to any name of any bean.
        String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
        boolean toParent = false;
        if (!StringUtils.hasLength(refName)) {

            // A reference to the id of another bean in the same XML file.
            refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
            if (!StringUtils.hasLength(refName)) {

                // A reference to the id of another bean in a parent context.
                refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
                toParent = true;
                if (!StringUtils.hasLength(refName)) {
                    error("'bean', 'local' or 'parent' is required for <ref> element", ele);
                    return null;
                }
            }
        }
        if (!StringUtils.hasText(refName)) {
            error("<ref> element contains empty target attribute", ele);
            return null;
        }
        RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
        ref.setSource(extractSource(ele));
        return ref;
    }

    //如果是idref子标签,则走这个方法
    else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
        return parseIdRefElement(ele);
    }

    //如果是value子标签,则走这个方法
    else if (nodeNameEquals(ele, VALUE_ELEMENT)) {

        //以这个方法作为演示,其他的方法都是大同小异,进入。
        return parseValueElement(ele, defaultValueType);
    }

    //如果是null子标签,则走这个方法
    else if (nodeNameEquals(ele, NULL_ELEMENT)) {

        // It's a distinguished null value. Let's wrap it in a TypedStringValue
        // object in order to preserve the source location.
        TypedStringValue nullHolder = new TypedStringValue(null);
        nullHolder.setSource(extractSource(ele));
        return nullHolder;
    }

    //如果是array子标签,则走这个方法
    else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
        return parseArrayElement(ele, bd);
    }

    //如果是list子标签,则走这个方法
    else if (nodeNameEquals(ele, LIST_ELEMENT)) {
        return parseListElement(ele, bd);
    }

    //如果是set子标签,则走这个方法
    else if (nodeNameEquals(ele, SET_ELEMENT)) {
        return parseSetElement(ele, bd);
    }

    //如果是map子标签,则走这个方法
    else if (nodeNameEquals(ele, MAP_ELEMENT)) {
        return parseMapElement(ele, bd);
    }

    //如果是props子标签,则走这个方法
    else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
        return parsePropsElement(ele);
    }

    //否则返回null,报错
    else {
        error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
        return null;
    }
}

/**
* Return a typed String value Object for the given value element.
*
* 通过指定的value标签,返回指定的字符串value对象
*/
public Object parseValueElement(Element ele, String defaultTypeName) {

    // It's a literal value.
    //拿到value中的文本,包括回车、tab制表符、空格
    String value = DomUtils.getTextValue(ele);

    //有无type属性
    String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
    String typeName = specifiedTypeName;
    if (!StringUtils.hasText(typeName)) {

        //没有就用入参defaultTypeName
        typeName = defaultTypeName;
    }
    try {
        TypedStringValue typedValue = buildTypedStringValue(value, typeName);

        //这里设置为空
        typedValue.setSource(extractSource(ele));

        //这里为空字符串
        typedValue.setSpecifiedTypeName(specifiedTypeName);

        //返回typedValue
        return typedValue;
    }
    catch (ClassNotFoundException ex) {
        error("Type class [" + typeName + "] not found for <value> element", ele, ex);
        return value;
    }
}

3.2 decorateBeanDefinitionIfRequired

在生成了BeanDefinitionHolder以后,如果需要的话应该通过代理类对bean definition进行渲染。

跟踪标记3.2的方法

该方法的实现在BeanDefinitionParserDelegate类中

//3.2如果有要求的话渲染beanDefinition
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
    return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
}

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
    Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {

    BeanDefinitionHolder finalDefinition = definitionHolder;

    // Decorate based on custom attributes first.
    // 首先基于自定义属性进行渲染
    // 也就是bean标签上的属性,也就是node
    // 只有当这个node不属于名称空间beans才会进行渲染,这里就不进去看了
    NamedNodeMap attributes = ele.getAttributes();
    for (int i = 0; i < attributes.getLength(); i++) {
        Node node = attributes.item(i);
        finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
    }

    // Decorate based on custom nested elements.
    // 然后根据标签内嵌套的子标签进行渲染
    // 这里是不属于名称空间beans的子标签才会进行渲染
    NodeList children = ele.getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
        Node node = children.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
        }
    }
    return finalDefinition;
}

3.3 registerBeanDefinition

最终将完成的bean definition注册到工厂中

跟踪标记3.3的方法

//3.3注册最终被渲染的实例到工厂中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

/**
* Register the given bean definition with the given bean factory.
*
* 注册bean definition
*/
public static void registerBeanDefinition(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    throws BeanDefinitionStoreException {

    // Register bean definition under primary name.

    // 3.3.1注册bean definition的beanName
    // 比如tk.mybatis.spring.mapper.MapperScannerConfigurer#0
    String beanName = definitionHolder.getBeanName();

    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.

    // 如果有别名的话,为bean name注册别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {

            //3.3.2注册别名
            registry.registerAlias(beanName, alias);
        }
    }
}

3.3.1 registerBeanDefinition

跟踪标记3.3.1的方法

// 3.3.1注册bean definition的beanName
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {

            //做一个验证,静态工厂方法和覆盖方法不能组合使用
            //如果bean definition中的beanClass属性不是String类型而是Class类型
            //那么就要验证和准备这个bean定义的覆盖方法,检查指定名称的方法是否存在
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                   "Validation of bean definition failed", ex);
        }
    }

    BeanDefinition oldBeanDefinition;

    //查看beanName是否已经被注册在工厂的beanDefinitionMap属性中
    oldBeanDefinition = this.beanDefinitionMap.get(beanName);

    //已经被注册走这个方法,这里不查看
    if (oldBeanDefinition != null) {
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                   "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                                                   "': There is already [" + oldBeanDefinition + "] bound.");
        }
        else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {

            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
                                 "' with a framework-generated bean definition: replacing [" +
                                 oldBeanDefinition + "] with [" + beanDefinition + "]");
            }
        }
        else if (!beanDefinition.equals(oldBeanDefinition)) {
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Overriding bean definition for bean '" + beanName +
                                 "' with a different definition: replacing [" + oldBeanDefinition +
                                 "] with [" + beanDefinition + "]");
            }
        }
        else {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Overriding bean definition for bean '" + beanName +
                                  "' with an equivalent definition: replacing [" + oldBeanDefinition +
                                  "] with [" + beanDefinition + "]");
            }
        }
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {

        //这里面代表beanName还没有被注册
        //然后根据阶段不同又有一层判断
        if (hasBeanCreationStarted()) {

            //这个阶段是bean已经开始创建
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {

            // Still in startup registration phase

            // 仍然处于启动时的注册阶段
            // 所以这里走这个方法
            //beanDefinitionMap是工厂的一个属性,ConcurrentHashMap类型
            //他保存所有解析好的bean Definition的名称和实例的映射
            this.beanDefinitionMap.put(beanName, beanDefinition);

            //beanName也单独使用了一个ArrayList来保存,方便遍历
            this.beanDefinitionNames.add(beanName);

            //如果该bean definition是手动注册的,还要从manualSingletonNames中
            //移除bean definition的beanName,还要从manualSingletonNames中是LinkedHashSet
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    //这里跳过
    if (oldBeanDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

3.3.2 registerAlias

跟踪3.3.2方法

//3.3.2注册别名
registry.registerAlias(beanName, alias);

@Override
public void registerAlias(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
        //aliasMap是ConcurrentHashMap类型,保存别名和beanName的映射
        this.aliasMap.remove(alias);
    }
    else {
        String registeredName = this.aliasMap.get(alias);

        //如果别名对应beanName已经被注册,则不需要再注册一次
        //别名不允许被覆盖
        if (registeredName != null) {
            if (registeredName.equals(name)) {

                // An existing alias - no need to re-register
                return;
            }
            if (!allowAliasOverriding()) {
                throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                                                name + "': It is already registered for name '" + registeredName + "'.");
            }
        }

        //再检查一遍,aliasMap中不能已经存在name和alias
        checkForAliasCircle(name, alias);

        //工厂的aliasMap属性保存别名,那么alias已被注册
        this.aliasMap.put(alias, name);
    }
}

这样,spring配置文件中为bean标签的解析和加载,也就跟踪完了。

然后再看下非默认名称空间的标签的解析和加载。

因为字数超过了限制,所以分成了三篇,点击下篇继续阅读

https://www.jianshu.com/p/6e0f6fd1cbbd

  • 走解析默认元素的方法。根据beans名称空间下,不同的标签有不同的子方法,对于<bean>标签来说,主要分为三步:

    • 3.1 通过代理 delegate 解析 bean 元素生成 BeanDefinitionHolder
    • 如果有必要的话,利用非默认名称空间的属性和子标签,渲染 BeanDefinitionHolder 中的 BeanDefinition
    • 注册最终被渲染的实例到工厂中。分两步,一步注册 BeanDefinition ,其实就是将 beanName 和 BeanDefinition 放入 beanDefinitionMap 中,beanName 放入 beanDefinitionNames中;一步注册别名,将 alias、name放入到 aliasMap 中

——————————————————————————————————

  • 3.1
  • 获取元素上的 id、name 属性,id 作为 beanName,name 作为别名。如果没有指定 id,取 name 的一个值作为 beanName,别名中移除该值。
  • 解析元素生成 BeanDefinition
  • 如果属性没有指定 id 也没有指定 name,利用 beanDefinition 生成一个 beanName。当这个bean是内部bean,类的全限定名加#号再加哈希值;当是顶层bean,类的全限定名加#号再从0开始加数字,id已被注册数字就增1,直到唯一。有了 beanName,再以类的全限定名作为别名。
  • 利用 BeanDefinition ,beanName ,别名,生成 BeanDefinitionHolder 并返回

——————————————————————————————————

  • 解析元素生成 BeanDefinition

    • 根据 bean 元素中的 class 属性和 parent 属性创建 BeanDefinition
    • 将 bean 标签上的属性设置到 BeanDefinition 中,一些未明确指定的属性采用代理 delegate 中的 defaults 值
    • 解析 bean 标签下的子标签,如 Property 、constructor-arg 等,将其键值对添加到 BeanDefinition 中
    • 返回 BeanDefinition

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章