Spring bean 标签加载、解析过程分析
概述
上一篇【Spring 加载、解析applicationContext.xml 流程】分析了从xml文件加载到开始解析xml里面的标签为止,基本都是跟spring 真正的核心没什么关系。
这篇我们分析 applicationContext.xml 中的bean 标签解析。
parseDefaultElement() 方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.java
- 解析 import 标签
- 解析 alias 标签
- 解析 bean 标签
- 解析 beans 标签
processBeanDefinition() 方法
- 解析bean标签(id、name、alias、class、score ...),并封装成BeanDefinitionHolder 对象返回。
- decoreBeanDefinitionIfRequired() 方法解析自定义标签,如果bean标签中包含自定义标签,则解析自定义标签
- bean解析完成后,对bdHolder 进行注册。
parseBeanDefinitionElement() 方法
解析id和name属性,name属性可以配置多个值,以逗号分割。name中的值相当于<alias></alias>中配置的值
- 调用parseBeanDefinitionElement()方法,解析bean标签的其它属性,返回一个GenericBeanDefinition对象
- 判断beanName是否有值,如果没有则自动生成beanName
- 构造BeanDefinitionHolder 对象,并返回
parseBeanDefinitionElement() 方法
- 创建 GenericBeanDefinition 对象
- 解析bean的所有属性
- 解析 <description> 标签
- 解析 <meta> 标签
- 解析<lookup-method/> 标签
- 解析 <replaced-method> 标签
- 解析 <constructor-arg> 标签
- 解析 <property> 标签
- 解析 <qualifier> 标签
1. 创建 GenericBeanDefinition 对象
createBeanDefinition()方法
创建GenericBeanDefinition实例
GenericBeanDefinition 继承了 AbstractBeanDefinition。
AbstractBeanDefinition 对应这一个<bean>标签,bean标签中每一个属性都能在AbstractBeanDefinition 中找到对应的元素。
2. 解析bean的所有属性
AbstractBeanDefinition() 方法
解析bean标签的各种属性, 然后存储到GenericBeanDefinition 对象中,并返回。
<!-- 配置的bean标签属性 -->
<bean id="" name="" class="" lazy-init="default" abstract="true" autowire-candidate="default"
autowire="default" depends-on="" destroy-method="" factory-bean="" factory-method=""
init-method="" primary="true" scope="" />
3. 解析 <description> 标签
调用DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)方法解析
4. 解析 <meta> 标签
5. 解析<lookup-method/> 标签
6. 解析 <replaced-method> 标签
7. 解析 <constructor-arg> 标签
- 解析index、type、name 属性
- 构造ConstructorArgumentValues.ValueHolder对象,把name、type、name、value存储到该对象中
- 如果有index属性,则把 valueHolder 存储到ConstructorArgumentValues.indexedArgumentValues 属性中
- 如果没有index属性,则把valueHolder存储到ConstructorArgumentValues .genericArgumentValues 属性中
ConstructorArgumentValues 类结构
public class ConstructorArgumentValues {
private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<>(0);
private final List<ValueHolder> genericArgumentValues = new LinkedList<>();
......
public static class ValueHolder implements BeanMetadataElement {
@Nullable
private Object value;
@Nullable
private String type;
@Nullable
private String name;
@Nullable
private Object source;
private boolean converted = false;
@Nullable
private Object convertedValue;
......
}
}
8. 解析 <property> 标签
解析<property>的子标签
parsePropertyElement()
调用parsePropertyValue() 方法获取property的值。
parsePropertyValue() 方法
- 获取子标签,并跳过 meta 和 description 标签的解析
- 获取 property 的ref 和value 的属性。
- 如果即存在 ref 属性又存在 value 属性,或者存在ref 或value 属性的同时还存在子标签,则标签规则错误。
- 如果存在ref 属性,则使用RuntimeBeanReference对象封装ref
- 如果存在value属性,则使用TypeStringValue封装
- 如果存在子标签则处理解析子标签
**解析子标签 parsePropertySubElement() **
- 如果不是默认的标签,则执行嵌套自定义标签解析
- 解析bean标签
- 解析ref 标签
- 解析idref 标签
-
解析value标签
- 解析null标签
- 解析array标签
- 解析list标签
- 解析set 标签
- 解析map标签
- 解析prop标签
9. 解析 <qualifier> 标签
解析完bean的所有属性,子标签后和自定义标签后存储到 GenericBeanDefinition 对象中,然后调用DefaultListableBeanFactory.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());把beanDefinitoin注册到 beanDefinitionMap中。
beanDefinitionMap 定义
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
想了解更多精彩内容请关注我的公众号