spring源码(5)父子beans标签之间的属性关系

一、父子beans标签之间的属性关系

回忆之前的一段代码:

protected void doRegisterBeanDefinitions(Element root) {
    String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
    if (StringUtils.hasText(profileSpec)) {
        String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        if (!getEnvironment().acceptsProfiles(specifiedProfiles)) {
            return;
        }
    }

    // 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(this.readerContext, root, parent);

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

    this.delegate = parent;
}

这是BeanDefinitionDocumentReader对Document解析的开始,从注释

Any nested <beans> elements will cause recursion in this method

我们知道,任何一个beans标签的解析都会调用这个方法。所以我们也可以说着是对beans标签的解析,参数root就是beans标签。

在这段代码中,又委托BeanDefinitionParserDelegate实例delegate对beans标签进行解析,每次解析一个beans标签,就根据上一个delegate重新创建一个BeanDefinitionParserDelegate对象。

根据上一个delegate重新创建一个BeanDefinitionParserDelegate对象?

protected BeanDefinitionParserDelegate createDelegate(
        XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {

    BeanDefinitionParserDelegate delegate = createHelper(readerContext, root, parentDelegate);
    if (delegate == null) {
        delegate = new BeanDefinitionParserDelegate(readerContext, getEnvironment());
        delegate.initDefaults(root, parentDelegate);
    }
    return delegate;
}

public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
    populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
    this.readerContext.fireDefaultsRegistered(this.defaults);
}

protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
    //如果beans标签定义了default-lazy-init属性
    String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
    //如果default-lazy-init是属性值为default
    if (DEFAULT_VALUE.equals(lazyInit)) {
        //如果上一个delegate的default-lazy-init的属性值不为null,则去上一次的值
        lazyInit = parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE;
    }
    defaults.setLazyInit(lazyInit);
...

在delegate中使用DocumentDefaultsDefinition的实例defaults进行beans标签属性值的保存。

public class DocumentDefaultsDefinition implements DefaultsDefinition {

private String lazyInit;

private String merge;

private String autowire;

private String dependencyCheck;

private String autowireCandidates;

private String initMethod;

private String destroyMethod;

private Object source;
...

}

新建的BeanDefinitionParserDelegate对象delegate会继承上一次delegate的属性。

二、断点测试


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">

  <beans default-lazy-init="true">
    <beans default-lazy-init="default">
        <bean name="dog" lazy-init="default" class="com.test.Dog"></bean>
    </beans>
  </beans>

</beans>

delegate的默认属性(defaults:DocumentDefaultsDefinition)值表:

第一个beans:

序号属性名属性值
1lazyInitfalse

第二个beans:

序号属性名属性值
1lazyInittrue

第三个beans:

序号属性名属性值
1lazyInittrue

bean的lazy-init属性值为true。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值