DefaultBeanDefinitionDocumentReader的类层次图:
接口中定义了一个方法,注册xml中的bean
public interface BeanDefinitionDocumentReader {
void registerBeanDefinitions(Document var1, XmlReaderContext var2) throws BeanDefinitionStoreException;
}
子类实现:
//readerContext一般是XmlReaderContext,在XmlBeanDefinitionReader中创建
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
this.doRegisterBeanDefinitions(root);
}
主要内容:
- 获取delegate,看看有没有委托的reader(默认一般是没有的)
- 然后创建BeanDefinitionParserDelegate,赋值给delegate
- 使用delegate判断root(根节点一般是beans)节点是不是默认命名空间的
- 看看根节点的profile属性,是不是可以被接受的,如果不被接受,则直接返回。在beans上加profile属性,可以指定dev或者production模式。可以用于数据库配置。在web.xml中指定项目的模式。
- 开始解析document
- 是默认命名空间的节点,由当前类解析,否则由delegate解析
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
//创建的是BeanDefinitionParserDelegate
if(this.delegate.isDefaultNamespace(root)) {//判断根节点是不是默认命名空间,如果是,获取应用环境
String profileSpec = root.getAttribute("profile");
if(StringUtils.hasText(profileSpec)) {//判断这个节点的应用环境是不是符合要求,比如是不是生产环境,如果不是,则不解析这个root节点下的内容
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if(this.logger.isInfoEnabled()) {
this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
}
return;
}
}
}
this.preProcessXml(root);//默认空
this.parseBeanDefinitions(root, this.delegate);
this.postProcessXml(root);//默认空
this.delegate = parent;
}
从根节点开始遍历
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
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)) {
this.parseDefaultElement(ele, delegate);
} else {
delegate.parseCustomElement(ele);//委托解析
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
如果是默认命名空间的节点:
默认命名空间http://www.springframework.org/schema/beans
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if(delegate.nodeNameEquals(ele, "import")) {//等价于新解析一个配置文件
this.importBeanDefinitionResource(ele);
} else if(delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);
} else if(delegate.nodeNameEquals(ele, "bean")) {//使用BeanDefinitionParserDelegate解析
this.processBeanDefinition(ele, delegate);
} else if(delegate.nodeNameEquals(ele, "beans")) {//一般根节点就是这个节点,如果是,则遍历解析子节点
this.doRegisterBeanDefinitions(ele);
}
}
不是默认命名空间,由BeanDefinitionParserDelegate解析。
public BeanDefinition parseCustomElement(Element ele) {
return this.parseCustomElement(ele, (BeanDefinition)null);
}
所以最后实际的能有产出的解析工作,是由BeanDefinitionParserDelegate完成的。