默认标签的解析是在 parseDefaultElement 函数中进行的,分别针对四种不同标签(import、alias、bean、beans),代码如下:
1. bean 标签的解析和注册
在四种标签的解析中,对 bean 标签的解析最为复杂也最为重要,所以先从 bean 标签的解析开始。首先进入 bean 标签解析方法:
时序图如下:
1.1 解析 BeanDefinition
以上就是对默认标签解析的全过程,对 Spring 的解析像剥洋葱一样,一层一层地进行,尽管现在只能看到对属性 id 以及 name 的解析,但是思路就是这样的。再开始对属性进行全面解析前,Spring 在外层又做了一个当前层的功能架构,主要工作内容在代码中已经添加了相应的注释。
步骤一没什么好说的,这里查看下步骤 2 中对标签其它属性的解析过程:
终于,bean 标签的所有属性,不论常用不常用都看到了。接下来继续一些复杂标签属性的解析。
1.1.1 创建用于属性承载的 BeanDefinition
BeanDefinition 是一个接口,在 Spring 中存在三种实现:RootBeanDefinition、ChildBeanDefinition 以及 GenericBeanDefinition。三种实现都继承了 AbstractBeanDefinition,其中 BeanDefinition 是配置文件中 bean 元素标签在容器中的内部表现形式。bean 元素标签拥有 class、scope、lazy-init 等配置属性,BeanDefinition 则提供了相应的 beanClass、scope、lazyInit 属性,BeanDefinition 和 bean 元素标签中的属性是一一对应的。其中 RootBeanDefinition 是最常用的实现类,它对应一般性的 bean 元素标签,GenericBeanDefinition 是自 2.5 版本以后新加入的 bean 文件配置属性定义类,是一站式服务类。
在配置文件中可以定义父 bean 元素标签和子 bean 元素标签,父 bean 元素标签用 RootBeanDefinition 表示,而子元素标签用 ChildBeanDefinition 表示,而没有父 bean 元素标签的 标签就是用 RootBeanDefinition 表示。AbstractBeanDefinition 对两者共同的类信息进行抽象。
Spring 通过 BeanDefinition 将配置文件中的 bean 元素标签配置信息转换为容器的内部表示,并将这些 BeanDefinition 注册到 BeanDefinitionRegistry 中。Spring 容器的 BeanDefinitionRegistry 就像是 Spring 配置信息的内存数据库,主要以 map 形式保存,后续操作直接从 BeanDefinitionRegistry 中读取配置信息。关系图如下:
要解析属性,首先要创建用于承载属性的实例,也就是创建 GenericBeanDefinition 类型的实例。而代码 createBeanDefinition(className, parent) 的作用就是实现此功能。代码如下:
1.1.2 解析各种属性
创建了承载属性实例后,便可以进行 bean 信息的属性解析了,首先进入 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd) 方法:
1.1.3 解析子元素 meta
对 meta 属性的解析代码如下:
1.1.4 解析子元素 lookup-method
这个方法和 parseMetaElements 的代码大同小异,最大的区别是 if 判断中的节点名称在这里是 LOOKUP_METHOD_ELEMENT 。还有,在数据存储上面通过使用 LookupOverride 类型的实体类进行数据承载并记录在 AbstractBeanDefinition 中的 methodOverrides 属性中。