简单的了解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--day46--MySQL自定义函数

    1,mysql自定义函数(mysql函数会降低查找速度,使用 了函数的行和列不能再用索引查找了,这样对性能要求高的需求就不能这样写) 函数调用 select f(参数1,参数2): 对函数进行调用:

  2. P1103 走迷宫三

    题目描述 大魔王抓住了爱丽丝,将她丢进了一口枯井中,并堵住了井口. 爱丽丝在井底发现了一张地图,他发现他现在身处一个迷宫当中,从地图中可以发现,迷宫是一个N*M的矩形,爱丽丝身处迷宫的左上角,唯一的出 ...

  3. ES6 set和map数据结构对对象数组去重简单实现

    自从有了es6的set数据结构,数组的去重可以简单用一行代码实现,比如下面的方式 let arr = [1, 2, 2, 3, 4] function unique (arr) { return [. ...

  4. Redux 认识之后进阶

    两个东西 action  状态 路由 以及嵌套路由 完整结构   进阶+源代码 源代码在我的 gitHub  存储库里面  https://github.com/Haisenan/Redux2.0

  5. linux自旋锁函数

    我们已经看到 2 个函数, spin_lock 和 spin_unlock, 可以操作自旋锁. 有其他几个函 数, 然而, 有类似的名子和用途. 我们现在会展示全套. 这个讨论将带我们到一个我们无 法 ...

  6. 【矩阵乘法优化dp】[Codeforces 621E] Wet Shark and Blocks

    http://codeforces.com/problemset/problem/621/E E. Wet Shark and Blocks time limit per test 2 seconds ...

  7. Nutch2.3 编译和安装配置

    Nutch2.3 编译和安装配置 [一].介绍 Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫.现在Nutch分为两个版本:1. ...

  8. 基于Nutch+Hadoop+Hbase+ElasticSearch的网络爬虫及搜索引擎

    基于Nutch+Hadoop+Hbase+ElasticSearch的网络爬虫及搜索引擎 网络爬虫架构在Nutch+Hadoop之上,是一个典型的分布式离线批量处理架构,有非常优异的吞吐量和抓取性能并 ...

  9. 011.MFC_Slider

    滑块CSliderCtrl 常用函数SetLineSize() GetLineSize() SetPageSize() GetPageSize()SetRangeMax() GetRangeMax() ...

  10. Ambari+HDP+HDF离线安装包下载清单

    Ambari 2.7.3 Repositories OS Format URL RedHat 7 CentOS 7 Oracle Linux 7 Base URL http://public-repo ...