Spring bean 标签加载、解析过程分析

概述

上一篇【Spring 加载、解析applicationContext.xml 流程】分析了从xml文件加载到开始解析xml里面的标签为止,基本都是跟spring 真正的核心没什么关系。 这篇我们分析 applicationContext.xml 中的bean 标签解析。

parseDefaultElement() 方法

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.java

  1. 解析 import 标签
  2. 解析 alias 标签
  3. 解析 bean 标签
  4. 解析 beans 标签

processBeanDefinition() 方法

  1. 解析bean标签(id、name、alias、class、score ...),并封装成BeanDefinitionHolder 对象返回。
  2. decoreBeanDefinitionIfRequired() 方法解析自定义标签,如果bean标签中包含自定义标签,则解析自定义标签
  3. bean解析完成后,对bdHolder 进行注册。

parseBeanDefinitionElement() 方法

解析id和name属性,name属性可以配置多个值,以逗号分割。name中的值相当于<alias></alias>中配置的值

  1. 调用parseBeanDefinitionElement()方法,解析bean标签的其它属性,返回一个GenericBeanDefinition对象
  2. 判断beanName是否有值,如果没有则自动生成beanName
  3. 构造BeanDefinitionHolder 对象,并返回

parseBeanDefinitionElement() 方法

  1. 创建 GenericBeanDefinition 对象
  2. 解析bean的所有属性
  3. 解析 <description> 标签
  4. 解析 <meta> 标签
  5. 解析<lookup-method/> 标签
  6. 解析 <replaced-method> 标签
  7. 解析 <constructor-arg> 标签
  8. 解析 <property> 标签
  9. 解析 <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> 标签

  1. 解析index、type、name 属性
  2. 构造ConstructorArgumentValues.ValueHolder对象,把name、type、name、value存储到该对象中
  3. 如果有index属性,则把 valueHolder 存储到ConstructorArgumentValues.indexedArgumentValues 属性中
  4. 如果没有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() 方法

  1. 获取子标签,并跳过 meta 和 description 标签的解析
  2. 获取 property 的ref 和value 的属性。
  3. 如果即存在 ref 属性又存在 value 属性,或者存在ref 或value 属性的同时还存在子标签,则标签规则错误。
  1. 如果存在ref 属性,则使用RuntimeBeanReference对象封装ref
  2. 如果存在value属性,则使用TypeStringValue封装
  3. 如果存在子标签则处理解析子标签

**解析子标签 parsePropertySubElement() **

  1. 如果不是默认的标签,则执行嵌套自定义标签解析
  2. 解析bean标签
  3. 解析ref 标签
  4. 解析idref 标签
  5. 解析value标签
  1. 解析null标签
  2. 解析array标签
  3. 解析list标签
  4. 解析set 标签
  5. 解析map标签
  6. 解析prop标签

9. 解析 <qualifier> 标签

解析完bean的所有属性,子标签后和自定义标签后存储到 GenericBeanDefinition 对象中,然后调用DefaultListableBeanFactory.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());把beanDefinitoin注册到 beanDefinitionMap中。

beanDefinitionMap 定义

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏从零开始学 Web 前端

从零开始学 Web 之 jQuery(八)each,多库共存,包装集,插件

each 方法用来遍历 jQuery 对象的,它的参数是一个事件处理函数,这个事件处理函数有两个参数,第一个参数是索引,第二个参数时索引对应的 DOM 对象,使...

12840
来自专栏瓜大三哥

matlab GUI基础1

GUI编程开发 1.句柄图形 是一种面向对象的绘图系统。这些细节一般隐藏在图形M文件的内部,用户通过句柄图形可以定制图形的许多特性,这是使用高级绘图函数无法实现...

30380
来自专栏前端杂货铺

typeof的一些兼容性问题

typeof存在一些兼容性的问题,在IE6,7,8中的DOM和BOM元素及其对象上的方法的判定会出现误差,在safari上对NodeList实例 的判定,对Ex...

357150
来自专栏技术墨客

React学习(2)——状态、事件与动态渲染 原

    上一篇文章最后说明了组件传入的参数必须是只读的,但是在丰富的前端应用中,页面样式是时时刻刻会发生变化的。在前面的章节中介绍了一个时钟的例子,通过重复调用...

23610
来自专栏JetpropelledSnake

Vue学习笔记之Vue指令系统介绍

所谓指令系统,大家可以联想咱们的cmd命令行工具,只要我输入一条正确的指令,系统就开始干活了。

10740
来自专栏web前端教室

web前端零基础课-1012上周总结

类组件中的方法内部不绑定this,在方法内部使用this,需要用bind(this)传入

10620
来自专栏卡少编程之旅

四个Vue的写法优化技巧

36360
来自专栏BestSDK

“Excel格式”最风骚玩法,炫技加薪就靠它了

话不多说直接上干货! 001 自定义格式概述 01 调出单元格格式对话框 选中需要设置格式的单元格,按「CTRL+1」快捷键打开「设置单元格格式」对话框。 在对...

37630
来自专栏nice_每一天

如何编写高效的jQuery代码(转载)

1. jQuery速度再快,也无法与原生的javascript方法相比,而且建立的jQuery对象包含的信息量很庞大。所以有原生方法可以使用的场合,尽量避免使...

7920
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第四天 jQuery学习

jQuery是一个JavaScript框架。它兼容CSS3,还兼容各种浏览器。文档说明很全,应用详细,成熟插件多。

16840

扫码关注云+社区

领取腾讯云代金券