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>节点。

posted @ 2018-04-03 17:31  jintian315  阅读(213)  评论(0编辑  收藏  举报