本文作者:chenssy
出处:http://cmsblogs.com/?p=2697
在学习
Spring源码
的过程中发现的好站+好贴,感谢作者。Spring版本:Spring 5.0.6.RELEASE
获取 Document
对象后,会根据该对象和 Resource
资源对象调用 registerBeanDefinitions()
方法,开始注册 BeanDefinitions
之旅。如下:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { |
首先调用 createBeanDefinitionDocumentReader()
方法实例化 BeanDefinitionDocumentReader
对象,然后获取统计前 BeanDefinition
的个数,最后调用 registerBeanDefinitions()
注册 BeanDefinition
。 实例化 BeanDefinitionDocumentReader
对象方法如下:
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { |
注册 BeanDefinition
的方法 registerBeanDefinitions()
是在接口 BeanDefinitionDocumentReader
中定义,如下:
void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) |
从给定的 Document 对象中解析定义的 BeanDefinition 并将他们注册到注册表中。
方法接收两个参数,待解析的 Document
对象,以及解析器的当前上下文,包括目标注册表和被解析的资源。其中 readerContext
是根据 Resource
来创建的,如下:
public XmlReaderContext createReaderContext(Resource resource) { |
DefaultBeanDefinitionDocumentReader
对该方法提供了实现:
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { |
调用 doRegisterBeanDefinitions()
开启注册 BeanDefinition
之旅。
protected void doRegisterBeanDefinitions(Element root) { |
程序首先处理 profile
属性,profile
主要用于我们切换环境,比如切换开发、测试、生产环境,非常方便。然后调用 parseBeanDefinitions()
进行解析动作,不过在该方法之前之后分别调用 preProcessXml()
和 postProcessXml()
方法来进行前、后处理,目前这两个方法都是空实现,交由子类来实现。
protected void preProcessXml(Element root) { |
parseBeanDefinitions()
定义如下:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { |
最终解析动作落地在两个方法处:parseDefaultElement(ele, delegate)
和 delegate.parseCustomElement(root)
。我们知道在 Spring 有两种 Bean 声明方式:
- 配置文件式声明:
<bean id="studentService" class="org.springframework.core.StudentService"/>
- 自定义注解方式:
<tx:annotation-driven>
两种方式的读取和解析都存在较大的差异,所以采用不同的解析方法,如果根节点或者子节点采用默认命名空间的话,则调用 parseDefaultElement()
进行解析,否则调用 delegate.parseCustomElement()
方法进行自定义解析。 至此,doLoadBeanDefinitions()
中做的三件事情已经全部分析完毕,下面将对 Bean
的解析过程做详细分析说明。