Spring容器的实现
- BeanFactory
- ApplicationContext
对于XML文件而言,Spring容器的实现过程
- XmlBeanFactory
- 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