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:

序號 屬性名 屬性值
1 lazyInit false

第二個beans:

序號 屬性名 屬性值
1 lazyInit true

第三個beans:

序號 屬性名 屬性值
1 lazyInit true

bean的lazy-init屬性值爲true。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章