xml bean factory 的解析过程的 堆栈大概是这样的:
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.findParserForElement(NamespaceHandlerSupport.java:84) at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74) at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1411) at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1401) at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:172) at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:142) at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:94) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:252) at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127) at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93) at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129) at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:613) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:514) - locked <0x509> (a java.lang.Object) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext. (ClassPathXmlApplicationContext.java:93) at AnnoIoCTest.main(AnnoIoCTest.java:7)
可见,spring xml 文件的解析 基本是由 XmlBeanDefinitionReader 完成的。
bean 在代码层面的定义, 其实可以是非常丰富的。 最常见的, 当然就是 xml 文件中的 bean 元素了吧。
如果考虑下注解, 那么很快可以想起 @Bean , 这个注解也显而易见的 定义了一个bean。除此之外呢? 其实还有很多, 不那么明显的:
有各种各样的 bean 的定义格式, 那么, 相应的, 肯定存在各种各样的 bean 定义格式的 parser。
BeanDefinitionParser , 顾名思义, 就是对命名空间 bean 的定义的解析器 :
XmlBeanDefinitionReader 有一个 documentReaderClass 默认就是DefaultBeanDefinitionDocumentReader , 要求所有的实现必须是其子类。
BeanDefinitionParser 是spring 必须要加载的 默认的 bean 定义解析器。
DefaultBeanDefinitionDocumentReader 源码:
protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; this.delegate = this.createDelegate(this.getReaderContext(), root, parent); if(this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute("profile"); if(StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; "); if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if(this.logger.isInfoEnabled()) { this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource()); } return; } } } this.preProcessXml(root); this.parseBeanDefinitions(root, this.delegate); this.postProcessXml(root); this.delegate = parent; } protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) { BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);// 可见, 默认是BeanDefinitionPeraserDelegation delegate.initDefaults(root, parentDelegate); return delegate; }
这里的 delegate 默认就是 BeanDefinitionPeraserDelegation , 这是整个spring 的解析的 目前来说的 唯一的 入口 , 它是非常非常重要的。最关键当然是 parseBeanDefinitions方法, 接着看:
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)) { // 默认命名空间就是 bean this.parseDefaultElement(ele, delegate); // 处理默认的元素,也就是bean 元素, 实际是 交给 delegate 解析 } else { delegate.parseCustomElement(ele); // 处理客户化定制的的元素, 这里的客户其实并不是我们定制的, 而是spring 定制的那些,比如contex,tx 等其他的命名空间 } } } } else { delegate.parseCustomElement(root); } }
而parseCustomElement 就是读取 那个命名空间,然后从 spring.handlers 找到对应的 handler 类, 然后 解析它, 同时把解析解析结果 注册到 当前上下文 , 也就是 listabelbeanFactory。
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = this.getNamespaceURI(ele); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if(handler == null) { this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } else { return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } }
这里的 handler 其实是 NamespaceHandlerSupport , 寻找实际的 parser , 是在其中这个方法中完成的:
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); // 这里, 又调用了 delegate, BeanDefinitionParser parser = (BeanDefinitionParser)this.parsers.get(localName); // NamespaceHandler 注册了很多的 parser if(parser == null) { parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }
返回的parser 是 对某个命名空间下的 某个 类型bean 的 解析器, 比如 context 命名空间下的 component-scan , 对应 ComponentScanBeanDefinitionParser 等等以此类推。
public class ContextNamespaceHandler extends NamespaceHandlerSupport{ public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); }}
component-scan 元素 对应 的ComponentScanBeanDefinitionParser 就是其中一个。
property-placeholder 对应 PropertyPlaceholderBeanDefinitionParser, 很明显, 实际是实例化并 注册了一个 PropertySourcesPlaceholderConfigurer
BeanDefinitionParser 接口, 其实就一个 方法:
public interface BeanDefinitionParser { BeanDefinition parse(Element var1, ParserContext var2);}
parse 方法的作用是 , 解析那个element, 然后向 ParserContext 注册。
参考:
http://blog.csdn.net/wenjiangchun/article/details/50629764