注 :源码对应版本为 4.2.8.RELEASE
一、XmlBeanDefinitionReader
xml解析工作实际上是交给 XmlBeanDefinitionReader,从命名中也可以很清楚的理解它的用意
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader
/**
* Register each bean definition within the given root {@code <beans/>} element.
*/
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
//是否是默认命名空间,因为一般我们的写法有两种
//一种是 <bean name="" class="">
//另一种是自定义扩展的标签 <mvc:annotation-driven/>
//判断是否是默认命名空间的规则是:node.getNamespaceUri() 是否是
//spring固定的命名空间 http://www.springframework.org/schema/beans
if (this.delegate.isDefaultNamespace(root)) {
//读取profile属性,这个属性可以区分 生产,测试等,一般比较少用。
//一般做法是使用maven打包指定profile
//也可以实现自己的配置中心,这里不做详细的介绍
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)) {
return;
}
}
}
//模版方法,默认实现为空,可以作为一个扩展点
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
//模版方法,默认实现为空,可以作为一个扩展点
postProcessXml(root);
this.delegate = parent;
}
/**
* Parse the elements at the root level in the document:
* "import", "alias", "bean".
* @param root the DOM root element of the document
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//处理beans
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//只处理Element节点
if (node instanceof Element) {
Element ele = (Element) node;
//处理 import alias bean
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
//自定义标签处理
else {
delegate.parseCustomElement(ele);
}
}
}
}
//自定义标签处理
else {
delegate.parseCustomElement(root);
}
}
默认标签的解析还是挺清楚的:
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);
}
}
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate
处理自定义表情部分代码:
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
//获取命名空间
String namespaceUri = getNamespaceURI(ele);
//根据命名空间获取相应的处理Handler,aop,jdbc,mvc都实现了相应的Handler,用户自定义的标签也需要实现该接口
// 使用 NamespaceHandlerResolver 来获取 相应的 NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//调用自定义的NamespaceHandler处理
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver
public NamespaceHandler resolve(String namespaceUri) {
//获取handlerMapping
Map<String, Object> handlerMappings = getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
//判断是否是对象类型
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
//类名称类型
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
//类型检查,是否实现了NamespaceHandler 接口
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//初始化,init接口实际上是需要用户实现了
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "] not found", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "]: problem with handler class file or dependent class", err);
}
}
}
/**
* Load the specified NamespaceHandler mappings lazily.
*/
private Map<String, Object> getHandlerMappings() {
if (this.handlerMappings == null) {
synchronized (this) {
if (this.handlerMappings == null) {
try {
//从这句代码我们可以看到Spring读取了所有的 META-INF/spring.handlers 文件
//我们也可以在aop,mvc等jar里面找到该文件
//该文件里面定义了什么 namespaceUri 使用哪个 NamespaceHandler 来解析
//如http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
//用户自定义标签也只要遵循这个规则就可以了
Properties mappings =
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isDebugEnabled()) {
logger.debug("Loaded NamespaceHandler mappings: " + mappings);
}
Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return this.handlerMappings;
}