博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring 之 BeanDefinition & BeanDefinitionParser
阅读量:5038 次
发布时间:2019-06-12

本文共 8704 字,大约阅读时间需要 29 分钟。

 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

posted on
2017-11-12 13:06 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/FlyAway2013/p/7820716.html

你可能感兴趣的文章
第四天 selenium的安装及使用
查看>>
关于js的设计模式(简单工厂模式,构造函数模式,原型模式,混合模式,动态模式)...
查看>>
KMPnext数组循环节理解 HDU1358
查看>>
android调试debug快捷键
查看>>
【读书笔记】《HTTP权威指南》:Web Hosting
查看>>
Inoodb 存储引擎
查看>>
数据结构之查找算法总结笔记
查看>>
Linux内核OOM机制的详细分析
查看>>
Android TextView加上阴影效果
查看>>
Requests库的基本使用
查看>>
C#:System.Array简单使用
查看>>
C#inSSIDer强大的wifi无线热点信号扫描器源码
查看>>
「Foundation」集合
查看>>
算法时间复杂度
查看>>
二叉树的遍历 - 数据结构和算法46
查看>>
类模板 - C++快速入门45
查看>>
[转载]JDK的动态代理深入解析(Proxy,InvocationHandler)
查看>>
centos7 搭建vsftp服务器
查看>>
RijndaelManaged 加密
查看>>
Android 音量调节
查看>>