七、Spring MVC 源码学习(DefaultBeanDefinitionDocumentReader)

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

一、类职责

解析dom中的import、alias元素,并委派(BeanDefinitionParserDelegate)处理beans、bean元素

二、主流程

———————————————————————————————-

DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(Document doc, XmlReaderContext readerContext)

1.获取文档根元素 //Element root = doc.getDocumentElement();

2.创建BeanDefinitionParserDelegate ,该类具体处理文档中的

3.排除掉Environment中不被接受地profile

4.文档处理前的 前置处理(空实现,方便扩展)//preProcessXml()

5.利用BeanDefinitionParserDelegate将文档解析为beanDefinition(下面进行具体分析) //parseBeanDefinitions

6.文档的后置处理(空实现,方便扩展)//postProcessXml();

    protected void doRegisterBeanDefinitions(Element root) {
            // Any nested <beans> elements will cause recursion in this method. In
            // order to propagate and preserve <beans> default-* attributes correctly,
            // keep track of the current (parent) delegate, which may be null. Create
            // the new (child) delegate with a reference to the parent for fallback purposes,
            // then ultimately reset this.delegate back to its original (parent) reference.
            // this behavior emulates a stack of delegates without actually necessitating one.
            BeanDefinitionParserDelegate parent = this.delegate;
            this.delegate = createDelegate(getReaderContext(), root, parent);

            if (this.delegate.isDefaultNamespace(root)) {
                String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
                if (StringUtils.hasText(profileSpec)) {
                    String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                            profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                    if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                    "] not matching: " + getReaderContext().getResource());
                        }
                        return;
                    }
                }
            }

            preProcessXml(root);
            parseBeanDefinitions(root, this.delegate);
            postProcessXml(root);

            this.delegate = parent;
        }

———————————————————————————————–

DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)

1.dom根元素是否存在于默认的命名空间中

1.1 在命名空间中 执行后续步骤

1.2 不在命名空间中,执行BeanDefinitionParserDelegate的定制处理(BeanDefinitionParserDelegate)

2.子元素是否存在于默认命名空间

2.1 在命名空间中,执行parseDefaultElement(ele, delegate)//下面分析;

2.2 不在命名空间中,执行BeanDefinitionParserDelegate的定制处理(BeanDefinitionParserDelegate)

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
            if (delegate.isDefaultNamespace(root)) {
                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;
                        if (delegate.isDefaultNamespace(ele)) {
                            parseDefaultElement(ele, delegate);
                        }
                        else {
                            delegate.parseCustomElement(ele);
                        }
                    }
                }
            }
            else {
                delegate.parseCustomElement(root);
            }
        }

———————————————————————————————————————–

DefaultBeanDefinitionDocumentReader.parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)

分别对import、beans、alias、bean元素做处理

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
            if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
                importBeanDefinitionResource(ele);
            }
            else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
                processAliasRegistration(ele);
            }
            else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
                processBeanDefinition(ele, delegate);
            }
            else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
                // recurse
                doRegisterBeanDefinitions(ele);
            }
        }

下面我们着重分析processBeanDefinition的过程

三、processBeanDefinition代码分析

1.把xml文档中的bean标签解析成BeanDefinitionHolder

实现由:BeanDefinitionParserDelegate.parseBeanDefinitionElement

2.对生成的BeanDefinitionHolder再次处理(针对以下两种情况)

2.1(attr属性空间与bean空间不一致)

    <!--外部命名空间为bean  内部却为p-->
    <bean id="viewResolver" p:prefix="/WEB-INF/view/" p:suffix=".jsp"/>

2.2(子标签内外空间不一致)

    <bean>
            <!-- 外部为bean空间,内部为task空间-->
            <task:scheduler id=""/>
    </bean>

调用BeanDefinitionParserDelegate.decorateIfRequired修饰处理

3.以beanName为K,以beanDefinition为V 存入beanFactory.beanDefinition

以beanName为K,以alias为V 存入beanFactory.alias

4.触发组件注册事件(空实现)

四、补充

1.对import标签的解析

如下:

     <import resource="com/test/dao/dao-${test}.xml" />

源码如下:

    protected void importBeanDefinitionResource(Element ele) {
            String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
            // Resolve system properties: e.g. "${user.dir}"
            location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
    }

分析:

1.先读取到import标签中的resource属性

2.使用Environment去替换${}代表的值

注:Environment中存储了系统属性(System.getProperty)和环境变量(System.getenv)


来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 七、Spring MVC 源码学习(DefaultBeanDefinitionDocumentReader)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏