Spring配置文件解析之BeanDefinitionDocumentReader详解
作者:军伟@
Spring中的BeanDefinitionDocumentReader
上一篇Spring配置文件解析之BeanDefinitionReader详解中我们已经了解到BeanDefinitionReader已经将Spring的xml配置文件解析成Document对象了,接下来的解析处理工作是在BeanDefinitionDocumentReader中对Document对象进行解析工作了。
BeanDefinitionDocumentReader接口及其实现类:
BeanDefinitionDocumentReader提供的方法:
public interface BeanDefinitionDocumentReader { void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) throws BeanDefinitionStoreException; }
在 BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader定义了对一些xml配置文件基本的元素的解析处理操作
在这里我们可能会有一个疑问,在Spring的xml配置文件中经常看到的aop等相关的配置是在什么地方解析处理的,其实他们都是通过NamespaceHandler实现类来完成的,接下来我们会对其进行详细的介绍。
在DefaultBeanDefinitionDocumentReader的registerBeanDefinitions方法中开始对Document进行解析。
@Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); }
在doRegisterBeanDefinitions中会创建BeanDefinitionParserDelegate来对Document进行解析
protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; //创建BeanDefinitionParserDelegate,真正xml中各种元素的解析 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); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("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; }
在parseBeanDefinitions会对Node进行判断,如果是上面配置默认解析的spring标签,则会在DefaultBeanDefinitionDocumentReader中进行解析,否则的话就需要 BeanDefinitionParserDelegate来委派找到解析处理器。
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)) { //默认的一些标签在DefaultBeanDefinitionDocumentReader进行解析 parseDefaultElement(ele, delegate); } else { //如果不是默认的就需要在通过委派模式来寻找解析处理器 delegate.parseCustomElement(ele); } } } } else { //如果不是默认的就需要在通过委派模式来寻找解析处理器 delegate.parseCustomElement(root); } }
在parseDefaultElement中会对一些默认的标签import,alias,bean,beans标签进行处理
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { //解析import标签 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } //解析alias标签 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } //解析bean标签 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } //解析beans标签,就是进行递归解析 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }
对bean标签解析,最终还是在BeanDefinitionParserDelegate中对元素进行处理解析生成BeanDefinitionHolder,其实bean元素的解析的结果是一个BeanDefinition对象,其包含了所有的bean的属性设置,processBeanDefinition中的BeanDefinitionReaderUtils的处理结果是将BeanDefinition注册到BeanFactory中。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //最终还是在BeanDefinitionParserDelegate中进行元素解析 //BeanDefinitionHolder是对BeanDefinition的封装,包括BeanDefinition,beanName,aliases BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { //处理的操作是将bean的元数据BeanDifinition注册到BeanFactory中 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
总结
BeanDefinitionDocumentReader中也没有对xml中的bean元素进行处理操作,其真正的处理操作是在BeanDefinitionParserDelegate中进行处理的,都是在为他人做嫁衣。
到此这篇关于Spring配置文件解析之BeanDefinitionDocumentReader详解的文章就介绍到这了,更多相关Spring中的BeanDefinitionDocumentReader内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!