简单的了解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容器工作机制的更多相关文章

  1. 我的Spring学习记录(二)

    本篇就简单的说一下Bean的装配和AOP 本篇的项目是在上一篇我的Spring学习记录(一) 中项目的基础上进行开发的 1. 使用setter方法和构造方法装配Bean 1.1 前期准备 使用sett ...

  2. 我的Spring学习记录(四)

    虽然Spring管理这我们的Bean很方便,但是,我们需要使用xml配置大量的Bean信息,告诉Spring我们要干嘛,这还是挺烦的,毕竟当我们的Bean随之增多的话,xml的各种配置会让人很头疼. ...

  3. 我的Spring学习记录(五)

    在我的Spring学习记录(四)中使用了注解的方式对前面三篇做了总结.而这次,使用了用户登录及注册来对于本人前面四篇做一个应用案例,希望通过这个来对于我们的Spring的使用有一定的了解. 1. 程序 ...

  4. Spring 学习记录3 ConversionService

    ConversionService与Environment的关系 通过之前的学习(Spring 学习记录2 Environment),我已经Environment主要是负责解析properties和p ...

  5. Spring 学习记录8 初识XmlWebApplicationContext(2)

    主题 接上文Spring 学习记录7 初识XmlWebApplicationContext refresh方法 refresh方法是定义在父类AbstractApplicationContext中的. ...

  6. Spring 学习记录6 BeanFactory(2)

    主题 除了Spring 学习记录5 BeanFactory 里写的几个接口外,BeanFactory的实现类还实现了一些其他接口,这篇文章主要介绍这些接口和实现类. 结构 DefaultListabl ...

  7. spring 学习(五):spring 事务

    spring 学习(五):spring 事务 事务概要 一个数据库事务通常包含了一个序列的对数据库的读/写操作.它的存在包含有以下两个目的: 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同 ...

  8. java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制

    ClassLoader的工作机制 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有Bootstrap ClassLoader. ...

  9. Spring学习记录1——IoC容器

    IoC容器 1.1  IoC概述 Ioc(Inverse of Control,控制反转)是Spring容器的内核.对于软件来说,即某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定,即由 ...

随机推荐

  1. Python--day40--全局解释器锁

    1,起一百个线程和起一百个进程所花的时间对比(开启效率的较量): import time from threading import Thread from multiprocessing impor ...

  2. Python--day39--进程池的回调函数callback

    运行结果:

  3. HDU 2871"Memory Control"(线段树区间和并+set.lower_bound)

    传送门 •题意 有 n 个内存单元(编号从1开始): 给出 4 种操作: (1)Reset :表示把所有的内存清空,然后输出 "Reset Now". (2)New x :表示申请 ...

  4. React---钩子函数

    钩子函数的状态有4个阶段: <p>1.初始化阶段  (componentWillMount() || componentDidMount()) </p>             ...

  5. H3C 环路避免机制四:定义最大值

  6. js 替换指定位置的字符串

    不多bb,直接代码 //str:原始字符串,index,开始位置,changeStr,改变后的字 changeStr(str,index,changeStr){ return str.substr(0 ...

  7. junit 测试套件Suite

    junit测试套件,就是可以运行一个测试类使得一个或一些测试类被junit测试运行 见代码: 测试套件类: import org.junit.runner.RunWith; import org.ju ...

  8. element ui 批量删除

    <el-table :data="tableData" stripe border style="width: 100%" @selection-chan ...

  9. Linux 标准 C 类型的使用

    尽管大部分程序员习惯自由使用标准类型, 如 int 和 long, 编写设备驱动需要一些小心 来避免类型冲突和模糊的 bug. 这个问题是你不能使用标准类型, 当你需要"一个 2-字节 填充 ...

  10. hdu 6579 Operation (在线线性基)

    传送门 •题意 一个数组a有n个数 m个操作 操作① 询问$[l,r]$区间的异或值 操作② 在数组末尾追加一个数x,数组长度变为$n+1$ 其中$l,r$不直接给出,其中$l=l%n+1,r=r%n ...