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解析对应的元素。

浙公网安备 33010602011771号