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