springframework源代码阅读杂记(2)---spring.handlers文件介绍

在Spring的使用过程中,会使用到各种标签元素,那么这些标签元素是怎么解析的呢?这个就与SPring的核心组件相关了。

 

springframework作为spring框架的最核心组件,提供了IOC和AOP的功能,

springframework中最核心的五的组件是SpringAop、SpringBean、SpringContext、SpringAspect和SpringCore。

 

SpringAop、SpringBean、SpringContext都包含了spring.handlers文件,表明他们能解析的xml元素。

spring-aop的spring.handlers文件如下:

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

spring-bean如下:

http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler

SpringContext如下:

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

 

spring-bean作为默认的配置根元素,不需要特别配置,这个从解析代码中就可以看出。

我们以XML解析为例来看下:

 ApplicationContext bc = new ClassPathXmlApplicationContext("./resources/spring-common.xml");
spring-common.xml的定义如下:
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.2.xsd">

      <context:property-placeholder location="classpath:foo.properties" />

<bean id="person" class="com.nuaa.SpringXMLConfig.Person"> 
    <property name="name" value="helloworldwangjy"></property>
    <property name="year" value="100"></property>
</bean> 
</beans>

new ClassPathXmlApplicationContext("./resources/spring-common.xml") 最终会调用DefaultBeanDefinitionDocumentReader的parseBeanDefinitions函数。
主要的解析函数如下:

DefaultBeanDefinitionDocumentReader

	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)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

流程图如下:

 

 

 

在BeanDefinitionParserDelegate中存在函数如下:

	public boolean isDefaultNamespace(String namespaceUri) {
		return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri));
	}

	public boolean isDefaultNamespace(Node node) {
		return isDefaultNamespace(getNamespaceURI(node));
	}

  BEANS_NAMESPACE_URI的定义如下:

public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";

  

从代码可以看出,如果是isDefaultNamespace返回true,就进入函数parseDefaultElement(ele, delegate),如果不是则进入函数delegate.parseCustomElement(ele);

parseDefaultElement函数中,则分别读取import 属性、alias属性 bean属性 或者beans属性进行解析。

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

  

delegate.parseCustomElement(ele)函数如下:

	public BeanDefinition parseCustomElement(Element ele) {
		return parseCustomElement(ele, null);
	}

	public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}  

 

首先获取元素的nameSpaceUri,然后根据nameSpaceUri获取指定的NamespaceHandler进行解析,

譬如property-placeholder元素,其配置如下:

<context:property-placeholder location="classpath:foo.properties" />

namespaceUri的值就是 http://www.springframework.org/schema/context

this.readerContext.getNamespaceHandlerResolver()获取到的是NamespaceHandlerResolver的实现类,为DefaultNamespaceHandlerResolver。

DefaultNamespaceHandlerResolver中包含了一个handlerMappings,

	/** Stores the mappings from namespace URI to NamespaceHandler class name / instance */
	private volatile Map<String, Object> handlerMappings;

  

handlerMappings其中存储了所有的nameSpaceUri及其对应的NamespaceHandler。

我们把 handlerMappings内容打印如下

"http://www.springframework.org/schema/aop" -> "org.springframework.aop.config.AopNamespaceHandler"
"http://www.springframework.org/schema/cache" -> "org.springframework.cache.config.CacheNamespaceHandler"
"http://www.springframework.org/schema/task" -> "org.springframework.scheduling.config.TaskNamespaceHandler"
"http://www.springframework.org/schema/p" -> "org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler"
"http://www.springframework.org/schema/util" -> "org.springframework.beans.factory.xml.UtilNamespaceHandler"
"http://www.springframework.org/schema/lang" -> "org.springframework.scripting.config.LangNamespaceHandler"
"http://www.springframework.org/schema/c" -> "org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler"
"http://www.springframework.org/schema/context" -> "org.springframework.context.config.ContextNamespaceHandler"
"http://www.springframework.org/schema/jee" -> "org.springframework.ejb.config.JeeNamespaceHandler"

http://www.springframework.org/schema/context的对应的解析类是org.springframework.context.config.ContextNamespaceHandler。获取到后就由org.springframework.context.config.ContextNamespaceHandler解析对应的元素。

 

posted @ 2017-07-13 19:57  王久勇  阅读(926)  评论(0编辑  收藏  举报