Spring 源码解析(四)解析配置文件1
通过前边分析,我们知道Spring配置文件已经被加载成了Document对象实例,接上一章,我们来分析下DefaultBeanDefinitionDocumentReader如何解析Document,进入registerBeanDefinitions方法
//org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader
1 /** 2 * {@inheritDoc} 3 * <p>This implementation parses bean definitions according to the "spring-beans" XSD 4 * (or DTD, historically). 5 * <p>Opens a DOM Document; then initializes the default settings 6 * specified at the {@code <beans/>} level; then parses the contained bean definitions. 7 */ 8 @Override 9 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { 10 this.readerContext = readerContext; 11 logger.debug("Loading bean definitions"); 12 Element root = doc.getDocumentElement(); 13 doRegisterBeanDefinitions(root); 14 }
第12行,获取spring配置文件跟节点,即<benas>节点
第13行,解析<benas>节点,进入方法
1 /** 2 * Register each bean definition within the given root {@code <beans/>} element. 3 * @throws IllegalStateException if {@code <beans profile="..."} attribute is present 4 * and Environment property has not been set 5 * @see #setEnvironment 6 */ 7 protected void doRegisterBeanDefinitions(Element root) { 8 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); 9 if (StringUtils.hasText(profileSpec)) { 10 Assert.state(this.environment != null, "Environment must be set for evaluating profiles"); 11 String[] specifiedProfiles = StringUtils.tokenizeToStringArray( 12 profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); 13 if (!this.environment.acceptsProfiles(specifiedProfiles)) { 14 return; 15 } 16 } 17 18 // Any nested <beans> elements will cause recursion in this method. In 19 // order to propagate and preserve <beans> default-* attributes correctly, 20 // keep track of the current (parent) delegate, which may be null. Create 21 // the new (child) delegate with a reference to the parent for fallback purposes, 22 // then ultimately reset this.delegate back to its original (parent) reference. 23 // this behavior emulates a stack of delegates without actually necessitating one. 24 BeanDefinitionParserDelegate parent = this.delegate; 25 this.delegate = createDelegate(this.readerContext, root, parent); 26 27 preProcessXml(root); 28 parseBeanDefinitions(root, this.delegate); 29 postProcessXml(root); 30 31 this.delegate = parent; 32 }
第25行,创建了BeanDefinitionParserDelegate实例(这个类的描述为--Stateful delegate class used to parse XML bean definitions.)
第28行,处理<benas>节点,进入方法
1 /** 2 * Parse the elements at the root level in the document: 3 * "import", "alias", "bean". 4 * @param root the DOM root element of the document 5 */ 6 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 7 if (delegate.isDefaultNamespace(root)) { 8 NodeList nl = root.getChildNodes(); 9 for (int i = 0; i < nl.getLength(); i++) { 10 Node node = nl.item(i); 11 if (node instanceof Element) { 12 Element ele = (Element) node; 13 if (delegate.isDefaultNamespace(ele)) { 14 parseDefaultElement(ele, delegate);//处理默认命名空间的Element 15 } 16 else { 17 delegate.parseCustomElement(ele);//处理用户定义命名空间的Element 18 } 19 } 20 } 21 } 22 else { 23 delegate.parseCustomElement(root); 24 } 25 }
第8行,获取<benas></beans>所有的子节点。然后循环解析这些子节点(节点是Elemet则解析)。
第14行,解析处理默认命名空间的Element,比如最常用的<bean></bean>节点。
第17行,解析用户自定义的命名空间的Element,比如常用的<context:component-scan />、<tx:advice />、<mvc:annotation-driven />。
如何解析Element下节介绍,我们来大致简单地总结下Spring是如何加载解析配置文件的,其实是把配置文件路径交给XmlBeanDefinitionReader实例处理最终生成BeanDefiniton
1、XmlBeanDefinitionReader实例将配置文件转换成Document对象。
2、XmlBeanDefinitionReader创建了BeanDefinitionDocumentReader实例、XmlReaderContext实例。
3、将XmlReaderContext实例、Document对象作为入参调用BeanDefinitionDocumentReader的registerBeanDefinitions方法解析Document对象。
4、BeanDefinitionDocumentReader获取Document对象的<benas></beans>节点,创建代理类实例BeanDefinitionParserDelegate来处理<beans></beans>节点。