【Spring源码】IOC实现-代码逻辑

文章目录

  • 一、XmlBeanFactory 实现 IOC
    • 简要叙述版
    • 详细解释版
      • 1.配置文件的封装(读取配置文件,封装成Resource资源)
      • 2.解析注册bean
        • 2.1 封装资源文件(编码处理,对参数Resource使用EncodedResource类进行封装)
        • 2.2 获取输入流(从Resource中获取对应的InputStream,使用上一步编码作为输入流的编码,构造InputSource)
        • 2.3 (使用前两步结果) 进入核心代码
      • 3.加载bean
        • 3.1 转换对应 beanName
        • 3.2 缓存中获取单例 bean
        • 3.3 从 bean 的实例中获取对象
        • 3.4 获取单例
        • 3.5 准备创建 bean
        • 3.6 循环依赖
        • 3.7 创建 bean
  • 二、补充内容:
    • 默认标签解析
      • (一)bean 标签
        • 1.解析出配置文件的各种属性(元素解析,信息提取)
        • 2.解析自定义标签
        • 3.对解析后配置文件的内容进行注册
        • 4.通知监听器,bean已经加载完成(目前 Spring 对此未做处理)
      • (二)alias(获取-->注册)
      • (三)import
        • 1.获取 resource 属性所表示的路径
        • 2.解析路径中的系统属性,格式如“${user.dir}”
        • 3.判定 location 是绝对路径还是相对路径
        • 4.如果是绝对路径:递归调用bean的解析过程,进行另一次的解析
        • 5.如果是相对路径:计算出绝对路径,进行解析
        • 6.通知监听器,解析完成

Spring容器的实现

  1. BeanFactory
  2. ApplicationContext

对于XML文件而言,Spring容器的实现过程

  1. XmlBeanFactory
  2. ClassPathXmlApplicationContext

一、XmlBeanFactory 实现 IOC

简要叙述版

一、读取配置文件–>解析配置文件–>加载bean
二、读取配置文件–>对文件进行编码处理–>使用该编码作为输入流编码,获取输入流–>获取对XML文件的验证模式–>加载XML文件,并得到对应的Document–>对bean的处理(默认标签解析)–>加载bean【知道加载谁–>从缓存加载–>实例化–>检查加载对象(beanName)对应的配置,没有就从上级找–>确定初始化策略】

详细解释版

1.配置文件的封装(读取配置文件,封装成Resource资源)

 封装ClassPathResource:读取Spring配置文件,返回Resource资源

2.解析注册bean

2.1 封装资源文件(编码处理,对参数Resource使用EncodedResource类进行封装)

2.2 获取输入流(从Resource中获取对应的InputStream,使用上一步编码作为输入流的编码,构造InputSource)

2.3 (使用前两步结果) 进入核心代码

2.3.1 从encodedResource中获取已经封装的Resource对象并在此从Resource中获取其中的inputStream
2.3.2 通过org.xml.sax.InputSource读取XML文件的方式来准备InputSource对象
2.3.3 (核心)将准备的数据通过参数传入真正的核心处理部分doLoadBeanDefinitions
   2.3.3.1 获取对XML文件的验证模式(DTD & XSD)
   2.3.3.2 加载XML文件,并得到对应的Document
    2.3.3.2.1 创建DocumentBuilderFactory
    2.3.3.2.2 通过DocumentBuilderFactory创建DocumentBuilder
    2.3.3.2.3 解析inputSource来返回Document对象
2.3.3.3 根据返回的Document注册Bean信息
    2.3.3.3.1 处理profile属性
    2.3.3.3.2 解析注册 BeanDefinition【对bean的处理(默认标签解析)】

3.加载bean

3.1 转换对应 beanName

3.2 缓存中获取单例 bean

3.3 从 bean 的实例中获取对象

3.4 获取单例

3.5 准备创建 bean

3.6 循环依赖

3.7 创建 bean

3.7.1 创建 bean 的实例
3.7.2 记录创建 bean 的 ObjectFactory
3.7.3 属性注入
3.7.4 初始化 bean
3.7.5 注册 DisposableBean

二、补充内容:

默认标签解析

(一)bean 标签

1.解析出配置文件的各种属性(元素解析,信息提取)

1.1 提取元素中的 id 和 name 属性
1.2 进一步解析其他所有属性,统一封装至GenericBeanDefinition 类型的实例中
  1.2.1 <定义解析完的位置> 创建 BeanDefinition(Bean信息的承载实例)
  1.2.2 <开始解析> 解析各种属性
1.3 如果检测到bean没有指定beanName,那么使用默认规则为此 bean 生成 beanName
1.4 将获取到的信息(解析到的所有属性,beanName,别名数组)封装到 BeanDefinitionHolder 的实例中

2.解析自定义标签

2.1 获取属性或者元素的命名空间 --> 判断该元素或者属性是否适用于自定义标签的解析条件
2.2 找出自定义类型所对应的 NamespaceHandler并进一步解析

3.对解析后配置文件的内容进行注册

3.1 通过 beanName 注册 BeanDefinition
  3.1.1 对 AbstractBeanDefinition 进行校验(校验 methodOverrides属性)
  3.1.2 对 beanName 已经注册的情况的处理。如果设置了不允许bean的覆盖,则需要抛出异常,否则直接覆盖
  3.1.3 加入 map 缓存
  3.1.4 清除:解析之前留下的对应 beanName 的缓存
3.2 通过别名注册 BeanDefiniton
  3.2.1 alias 和 beanName 相同:不处理,删除原有的 alias
  3.2.2 alias 覆盖:如果 aliasName 已经使用,并已指向另一 beanName,则需要用户的设置进行处理
  3.2.3 alias 循环检查:当 A->B 存在时,若再次出现 A->C->B 时,则会抛异常
  3.2.4 注册 alias

4.通知监听器,bean已经加载完成(目前 Spring 对此未做处理)

(二)alias(获取–>注册)

(三)import

1.获取 resource 属性所表示的路径

2.解析路径中的系统属性,格式如“${user.dir}”

3.判定 location 是绝对路径还是相对路径

4.如果是绝对路径:递归调用bean的解析过程,进行另一次的解析

5.如果是相对路径:计算出绝对路径,进行解析

6.通知监听器,解析完成

你可能感兴趣的:(------Spring,源码)