beanfactory篇-(十三)默认标签的解析过程-九零后大叔的技术博客

沙海 2021年4月24日09:20:47Java评论24字数 9384阅读31分16秒阅读模式
摘要

回顾:通过前面一章节的了解,我们基本上知道了applicationContext.xml文件的整体的反复的封装过程。在beanfactory篇-(十一)spring的核心过程一之bean描述信息的注册 这篇文章里面,有提到关键的一些代码,就是将bean描述信息注册到beanDefinitionMap中。但是中间有一步,我们直接就跳过去了,没有细致的进行追踪了解。本章节我们对该分支逻辑进行详细的了解。

文章源自JAVA秀-https://www.javaxiu.com/19908.html

回顾:通过前面一章节的了解,我们基本上知道了applicationContext.xml文件的整体的反复的封装过程。在beanfactory篇-(十一)spring的核心过程一之bean描述信息的注册 这篇文章里面,有提到关键的一些代码,就是将bean描述信息注册到beanDefinitionMap中。但是中间有一步,我们直接就跳过去了,没有细致的进行追踪了解。本章节我们对该分支逻辑进行详细的了解。 文章源自JAVA秀-https://www.javaxiu.com/19908.html

文章源自JAVA秀-https://www.javaxiu.com/19908.html

1. bean标签解析过程的整体理解

在下面的代码中,我们知道代码行BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());是关键核心代码,主要是把bean描述信息注册到beanDefinitionMap中。文章源自JAVA秀-https://www.javaxiu.com/19908.html

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            //关键核心代码,把bean描述信息(也就是BeanDefinitionHolder对象)注册到beanDefinitionMap中。
            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));
    }
}

然而本章节我们不关注bean描述信息的注册,而是关注bean描述信息的具体转换,也就是下面这行代码的过程。文章源自JAVA秀-https://www.javaxiu.com/19908.html

BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

通过前面的一章节,我们知道了一个bean描述信息通过了一个漫长的解析过程,终于从下面的标签信息文章源自JAVA秀-https://www.javaxiu.com/19908.html

<bean id="userService" name="userService" class="com.minesoft.tutorial.service.UserServiceImpl"
      scope="singleton"
      autowire="byType"
      abstract="false"
      lazy-init="true"
      factory-bean="userServiceXmlFactoryBean"
      factory-method="createUserService"
/>

被解析封装成为了Element对象。那么Element对象,是如何被转换成为一个BeanDefinitionHolder对象的呢?下面我们跟踪代码,一步一步解开这个疑问。文章源自JAVA秀-https://www.javaxiu.com/19908.html

注意:不管是上面的一段bean标签信息,还是Element对象,还是BeanDefinitionHolder对象,本质上都是一个东西,那就是bean描述信息,只不过给人展现的形态不一样而已。这种抽象的思想,是一个开发者需要多加理解的。文章源自JAVA秀-https://www.javaxiu.com/19908.html

2. Element对象到BeanDefinitionHolder对象解析过程

[1] 首先将转换成为一个BeanDefinitionHolder对象的工作委托给delegate对象(BeanDefinitionParserDelegate)文章源自JAVA秀-https://www.javaxiu.com/19908.html

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //将转换工作整体委托给BeanDefinitionParserDelegate对象处理
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            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));
    }
}

[2] 其次我们看看BeanDefinitionParserDelegate的parseBeanDefinitionElement方法的核心解析过程文章源自JAVA秀-https://www.javaxiu.com/19908.html

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

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    List<String> aliases = new ArrayList<String>();
    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) && !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) {
        checkNameUniqueness(beanName, aliases, ele);
    }

    //首先将Element对象转换成为AbstractBeanDefinition对象
    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 &&
                            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);
                return null;
            }
        }
        String[] aliasesArray = StringUtils.toStringArray(aliases);
        //其次通过AbstractBeanDefinition对象,来初始化成BeanDefinitionHolder对象(也就是需要注册到beanDefinitionMap中的对象)。
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}

[3] 我们进一步跟踪一下parseBeanDefinitionElement方法是如何将Element对象转换成为AbstractBeanDefinition对象的文章源自JAVA秀-https://www.javaxiu.com/19908.html

public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, BeanDefinition containingBean) {

    this.parseState.push(new BeanEntry(beanName));

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

    try {
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        //首先创建一个不含任何具体信息的初始化的AbstractBeanDefinition对象
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);

        //其次我们将Element对象的属性信息提取出来,初始化到AbstractBeanDefinition对象
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

        //然后我们将Element对象的meta标签信息提取出来,初始化到AbstractBeanDefinition对象
        parseMetaElements(ele, bd);

        //然后我们将lookup-method和replace-method信息从Element对象中提取出来,初始化到AbstractBeanDefinition对象
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

        //然后我们将构造参数信息从Element对象中提取出来,初始化到AbstractBeanDefinition对象
        parseConstructorArgElements(ele, bd);

        //然后我们将属性信息从Element对象中提取出来,初始化到AbstractBeanDefinition对象
        parsePropertyElements(ele, bd);
        parseQualifierElements(ele, bd);

        bd.setResource(this.readerContext.getResource());
        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;
}

[4] 我们进一步跟踪一下parseBeanDefinitionAttributes方法是如何将Element对象信息,逐步的提取到AbstractBeanDefinition对象的文章源自JAVA秀-https://www.javaxiu.com/19908.html

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
        BeanDefinition containingBean, AbstractBeanDefinition bd) {

    if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
        error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
    }
    else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
        bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
    }
    else if (containingBean != null) {
        // Take default from containing bean in case of an inner bean definition.
        bd.setScope(containingBean.getScope());
    }

    if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
        bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    }

    //从Element对象提取lazyInit信息,并初始化到AbstractBeanDefinition对象
    String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
    if (DEFAULT_VALUE.equals(lazyInit)) {
        lazyInit = this.defaults.getLazyInit();
    }
    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

    //从Element对象提取autowire信息,并初始化到AbstractBeanDefinition对象
    String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
    bd.setAutowireMode(getAutowireMode(autowire));

    //从Element对象提取dependencyCheck信息,并初始化到AbstractBeanDefinition对象
    String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
    bd.setDependencyCheck(getDependencyCheck(dependencyCheck));

    if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
        String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
        bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
    }

    //从Element对象提取autowireCandidate信息,并初始化到AbstractBeanDefinition对象
    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));
    }

    //从Element对象提取PRIMARY_ATTRIBUTE信息,并初始化到AbstractBeanDefinition对象
    if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
        bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
    }

    //从Element对象提取init-method信息,并初始化到AbstractBeanDefinition对象
    if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
        String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
        if (!"".equals(initMethodName)) {
            bd.setInitMethodName(initMethodName);
        }
    }
    else {
        if (this.defaults.getInitMethod() != null) {
            bd.setInitMethodName(this.defaults.getInitMethod());
            bd.setEnforceInitMethod(false);
        }
    }

    //从Element对象提取destroy-method信息,并初始化到AbstractBeanDefinition对象
    if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
        String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
        bd.setDestroyMethodName(destroyMethodName);
    }
    else {
        if (this.defaults.getDestroyMethod() != null) {
            bd.setDestroyMethodName(this.defaults.getDestroyMethod());
            bd.setEnforceDestroyMethod(false);
        }
    }

    //从Element对象提取factory-method信息,并初始化到AbstractBeanDefinition对象
    if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
        bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
    }
    if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
        bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
    }

    return bd;
}

通过上述逐步调用,我们终于了解了Element对象是如何被转换成为一个BeanDefinitionHolder对象的。文章源自JAVA秀-https://www.javaxiu.com/19908.html

beanfactory篇-(十三)默认标签的解析过程-九零后大叔的技术博客 文章源自JAVA秀-https://www.javaxiu.com/19908.html

更多知识请关注公众号文章源自JAVA秀-https://www.javaxiu.com/19908.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定