回顾上篇
上篇文章读取配置文件中,我们已经分析到spring如何读取配置文件(BeanFactoryTest.xml),并最终把配置文件转换成Document 对象。接下来Spring会去解析Document 对象,并将解析出来的信息放到BeanDefinition中。最后BeanDefinition会被封装到BeanDefinitionHolder中。接下来我们就跟着源码,看看这一步是如何来实现的。
分析源码实现
首先我们debug一下,看看解析BeanFactoryTest.xml配置文件后创建出来的BeanDefinition里面都有什么属性。
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
由于我们配置文件写的比较简单,只配置了一个id和class,所以在BeanDefinition中我们就看到一个beanClass属性的值是我们再配置文件中配置的。也就是说解析完配置文件之后,我们配置的class属性,就会保存在BeanDefinition的beanClass这个字段中。
下面我们就看看Spring怎么去解析Document对象,生成BeanDefinition的。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
在上面代码中(为了阅读方便,这里把try-catch的代码删除了),我们看到,获取到Document对象后,就把Document作为参数,传入了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, 然后调用BeanDefinitionDocumentReader的registerBeanDefinitions方法来去处理解析和注册的逻辑。前面读取XML,将XML配置文件转换成Document都是在XmlBeanDefinitionReader这个类里面进行处理的,现在使用BeanDefinitionDocumentReader来对Document对象进行解析和注册bean。这里很好的体现了面向对象里单一职责的原则。进入到registerBeanDefinitions方法里面,看看里面的处理逻辑。
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
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.
if (!getReaderContext().getEnvironment</