Spring学习记录2——简单了解Spring容器工作机制
简单的了解Spring容器内部工作机制
Spring的AbstractApplicationContext是ApplicationContext的抽象实现类,该抽象类的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程,这些处理过程清晰刻画了Spring容器启动时所执行的各项操作。
(1)初始化BeanFactory:根据配置文件实例化BeanFactory,在obtainFreshBeanFactory()方法中,首先调用refreshBeanFactory()方法刷新BeanFactory,然后调用getBeanFactory()方法获取BeanFactory。在这一步中,Spring将配置文件的信息装入容器的Bean定义注册表(BeanDefinitionRegistry)中,此时Bean还未初始化。
(2)调用工厂后处理器:根据反射机制从Bean定义注册表(BeanDefinitionRegistry)中找出所有实现了BeanFactoryPostProcessor接口的Bean,并调用其postProcessBeanFacotry()接口方法。(处理实现了对应接口的特殊Bean)。
(3) 注册Bean后处理器:根据反射机制从BeanDefinitionRegistry中找出所有实现了BeanPostProcessor接口的Bean,并将它们注册到容器Bean后处理器的注册表中。
(4) 初始化信息源
(5)初始化应用上下文事件广播器。
(6) 初始化其他特殊的Bean:这是一个钩子方法,子类可以借助这个方法执行一些特殊操作。
(7)注册事件监听器。
(8)初始化所有单实例的Bean,使用懒加载模式的Bean除外:初始化Bean后,将它们放到Spring容器的缓存池中。
(9) 发布上下文刷新时间:创建上下文刷新事件,事件广播器负责将这些事件广播到每个注册的事件监听器中。
Spring容器从加载配置文件到创建一个Bean的流程
(1) RecourceLoader装载配置文件,加载配置信息,并使用Resource表示这个配置文件资源。
(2) BeanDefinitionReader读取Resource所指向的配置文件资源,解析配置文件。配置文件中每个<Bean>解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry(Bean定义注册表)中。
(3) 容器扫描BeanDefinitionRegistry中的BeanDefinition,使用反射机制自动识别出Bean工厂后处理器(实现了BeanFactoryPostProcessor接口的Bean),然后调用这些Bean工厂后处理器对BeanDefinitionRegistry中的BeanDefinition进行加工处理,主要进行两项工作:
①对使用占位符<bean>的元素标签进行解析,得到最终配置值。这意味着对一些半成品式的BeanDefinition对象进行加工处理并得到成品的BeanDefinition对象。
②对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过反射机制找出所有属性编辑器的Bean(实现了java.beans.PropertyEditor接口的Bean),并自动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry)。
(4) Spring容器从BeanDefinitionRegistry中取出加工后的的BeanDefinition,并调用InstantiationStrategy着手进行Bean实例化工作。
(5) 在实例化Bean时,Spring容器使用BeanWrapper对Bean进行封装。BeanWrapper提供了以反射机制操作Bean的方法,它将结合该Bean的BeanDefinition及容器中的属性编辑器,完成Bean属性注入工作。
(6) 利用容器中注册的Bean后处理器,对已完成属性设置工作的Bean进行后续加工,装配出一个准备就绪的Bean。
Spring组件简介
BeanDefinition:
BeanDefinition是配置文件<bean>元素标签在容器中的内部标识,<bean>标签中拥有class、scope、lazy-init等配置属性,在BeanDefinition中也提供了相应的类属性。二者是一一对应的。
Spring通过BeanDefinition将配置文件中的<bean>配置信息转换为容器的内部标识,并将这些BeanDefinition注册到BeanDefinitionRegistry中,后续操作直接从BeanDefinitionRegisry中读取哦诶之信息。
InstantiationStrategy
负责根据BeanDefinition对象创建一个Bean实例,仅负责实例化Bean的操作,相当于执行new,不会参加Bean属性设置工作,属性填充由BeanWrapper完成。
BeanWrapper
相当于一个代理器,完成Bean属性填充工作。在Bean实例被InstantiationStrategy创建出来之后,容器将Bean实例通过BeanWrapper包装起来。Spring从容器的BeanDefinitionRegistry中获取BeanDefinition,从中获取Bean属性的配置信息ProperyValue,并使用属性编辑器对ProperyValue进行转换以得到Bean的属性值。完成属性植入工作。
属性编辑器
Bean的属性值在配置文件中对应的是字面值,而BeanWrapper在填充时将字面值正确转换为对应属性时就用到了属性编辑器。 任何实现了java.beans.PropertyEditor接口的类都是属性编辑器。主要功能是将外部的设置值转换为JVM内部的队友类型,实际上是一个类型转换器。
Spring学习记录2——简单了解Spring容器工作机制的更多相关文章
- 我的Spring学习记录(二)
本篇就简单的说一下Bean的装配和AOP 本篇的项目是在上一篇我的Spring学习记录(一) 中项目的基础上进行开发的 1. 使用setter方法和构造方法装配Bean 1.1 前期准备 使用sett ...
- 我的Spring学习记录(四)
虽然Spring管理这我们的Bean很方便,但是,我们需要使用xml配置大量的Bean信息,告诉Spring我们要干嘛,这还是挺烦的,毕竟当我们的Bean随之增多的话,xml的各种配置会让人很头疼. ...
- 我的Spring学习记录(五)
在我的Spring学习记录(四)中使用了注解的方式对前面三篇做了总结.而这次,使用了用户登录及注册来对于本人前面四篇做一个应用案例,希望通过这个来对于我们的Spring的使用有一定的了解. 1. 程序 ...
- Spring 学习记录3 ConversionService
ConversionService与Environment的关系 通过之前的学习(Spring 学习记录2 Environment),我已经Environment主要是负责解析properties和p ...
- Spring 学习记录8 初识XmlWebApplicationContext(2)
主题 接上文Spring 学习记录7 初识XmlWebApplicationContext refresh方法 refresh方法是定义在父类AbstractApplicationContext中的. ...
- Spring 学习记录6 BeanFactory(2)
主题 除了Spring 学习记录5 BeanFactory 里写的几个接口外,BeanFactory的实现类还实现了一些其他接口,这篇文章主要介绍这些接口和实现类. 结构 DefaultListabl ...
- spring 学习(五):spring 事务
spring 学习(五):spring 事务 事务概要 一个数据库事务通常包含了一个序列的对数据库的读/写操作.它的存在包含有以下两个目的: 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同 ...
- java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制
ClassLoader的工作机制 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有Bootstrap ClassLoader. ...
- Spring学习记录1——IoC容器
IoC容器 1.1 IoC概述 Ioc(Inverse of Control,控制反转)是Spring容器的内核.对于软件来说,即某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定,即由 ...
随机推荐
- Python--day40--全局解释器锁
1,起一百个线程和起一百个进程所花的时间对比(开启效率的较量): import time from threading import Thread from multiprocessing impor ...
- Python--day39--进程池的回调函数callback
运行结果:
- HDU 2871"Memory Control"(线段树区间和并+set.lower_bound)
传送门 •题意 有 n 个内存单元(编号从1开始): 给出 4 种操作: (1)Reset :表示把所有的内存清空,然后输出 "Reset Now". (2)New x :表示申请 ...
- React---钩子函数
钩子函数的状态有4个阶段: <p>1.初始化阶段 (componentWillMount() || componentDidMount()) </p> ...
- H3C 环路避免机制四:定义最大值
- js 替换指定位置的字符串
不多bb,直接代码 //str:原始字符串,index,开始位置,changeStr,改变后的字 changeStr(str,index,changeStr){ return str.substr(0 ...
- junit 测试套件Suite
junit测试套件,就是可以运行一个测试类使得一个或一些测试类被junit测试运行 见代码: 测试套件类: import org.junit.runner.RunWith; import org.ju ...
- element ui 批量删除
<el-table :data="tableData" stripe border style="width: 100%" @selection-chan ...
- Linux 标准 C 类型的使用
尽管大部分程序员习惯自由使用标准类型, 如 int 和 long, 编写设备驱动需要一些小心 来避免类型冲突和模糊的 bug. 这个问题是你不能使用标准类型, 当你需要"一个 2-字节 填充 ...
- hdu 6579 Operation (在线线性基)
传送门 •题意 一个数组a有n个数 m个操作 操作① 询问$[l,r]$区间的异或值 操作② 在数组末尾追加一个数x,数组长度变为$n+1$ 其中$l,r$不直接给出,其中$l=l%n+1,r=r%n ...