一、父子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。