BeanDefinition 的解析
下面从int count = registerBeanDefinitions(doc, resource)
这行代码入手,先找到registerBeanDefinitions
方法的源码:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
下面罗列一下方法中的逻辑:
- 创建一个 BeanDefinitionDocumentReader 对象
documentReader
- 获取 Spring 容器中已经注册的 BeanDefinition 的数量
调用documentReader
的registerBeanDefinitions
方法,初步分析这里完成了解析和向容器中注册 BeanDefinition 的过程。
- 通过简单运算得到本次注册的 BeanDefinition 的数量并返回。
这里主要关注一下步骤1和3。
documentReader
的创建
首先简单看一下documentReader
是如何创建的:
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanUtils.instantiateClass(this.documentReaderClass);
}
private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
DefaultBeanDefinitionDocumentReader.class;
这里从createBeanDefinitionDocumentReader
方法和documentReaderClass
成员变量的代码可以看出,这里通过反射创建了一个 DefaultBeanDefinitionDocumentReader 类型的对象。
下面再看最重要的registerBeanDefinitions
方法:
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
BeanDefinitionParserDelegate
的创建
这里看到了一个名为doXXX
的方法调用,应该就是这部分的核心逻辑了,这里传入的参数是doc.getDocumentElement()
,代表的是 XML 文件中的beans
标签。查看方法源码:
/**
* Register each bean definition within the given root { @code <beans/>} element.
*/
@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
// 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(getReaderContext(), root, par