这块主要讲 Docoment 对象中的各种标签解析成 BeanDefinition ,并且缓存到 BeanFactory 中。
解析得到 BeanDefinition
接下来,才正式的进入 Bean 的注册环节;这个时候使用 DefaultBeanDefinitionDocumentReader 来处理注册相关件逻辑;
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
解析 XML 结点,DefaultBeanDefinitionDocumentReader # doRegisterBeanDefinitions(Element root);
protected void doRegisterBeanDefinitions(Element root) {
// 如果有嵌套的bean定义那么就会引起递归的调用
// 为了保留默认属性及传播默认属性,保留当前父节点(可能为空)
BeanDefinitionParserDelegate parent = this.delegate;
// delegate:代表,相当于克隆了一份当前结点,并且还记录了父节点
this.delegate = createDelegate(getReaderContext(), root, parent);
// 判断当前结点的命名空间是否为默认的 http://www.springframework.org/schema/beans
// 根结点才有这个属性,例如:<beans xmlns="http://www.springframework.org/schema/beans"> ...</beans>
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
// 可能有多个profile,进行切分
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// We cannot use Profiles.of(...) since profile expressions are not supported
// in XML config. See SPR-12458 for details.
// 如果当前启动环境不匹配设置的任何profile,则不注册beanDefinition
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("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(root, this.delegate);
接下来的解析就分成了解析系统默认的标签以及自定义的标签解析。
- 默认标签包括:import、alias、bean、beans;
- 自定义的标签比如:aop 、tx 这些都属于自定义标签。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 默认的命名空间,http://www.springframework.org/schema/beans
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);
}
}