简单的了解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. Spring Boot JPA 懒加载

    最近在使用spring jpa 的过程中经常遇到懒加载的错误:"` org.hibernate.LazyInitializationException: could not initiali ...

  2. (二)Centos7下Yum更新安装PHP5.5,5.6,7.0

    yum源默认的版本太低了,手动安装有一些麻烦,想采用Yum更新安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包, ...

  3. 【codeforces 761C】Dasha and Password(动态规划做法)

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  4. 《代码整洁之道 中文版》高清 PDF 电子书下载

    代码整洁之道.PDF 下载 代码整洁之道.PDF 中文版 高清 PDF  电子书下载 代码整洁之道下载  点我下载 作者简介  · · · · · · Robert C. Martin,Object ...

  5. Java中的断言assert的用法

    Java陷阱之assert关键字 一.概述 在C和C++语言中都有assert关键,表示断言. 在Java中,同样也有assert关键字,表示断言,用法和含义都差不多. 二.语法 在Java中,ass ...

  6. Priest John's Busiest Day (2-sat)

    题面 John is the only priest in his town. September 1st is the John's busiest day in a year because th ...

  7. centos6.5单用户模式拯救系统

    系统出现启动异常,某个软件卡住了不能启动(按Fx键可以查看是哪个软件卡住了),需要进入单用户模式或修复模式对系统进行管理. 使用单用户模式有一个前提,只要系统引导器(grub)能正常工作,否则要进行系 ...

  8. Android Library的依赖方式及发布(转)

    还是那句老话,好记性不然烂笔头,在此整理 Android Studio 依赖相关 以及 如何发布项目到 JCenter Android Studio 添加依赖Module 依赖module 依赖是指在 ...

  9. 【sublime】Pretty Json插件的安装与配置使用

    一.安装 Package Control  代码安装 从菜单 View - Show Console 或者 ctrl + ~ 快捷键,调出 console.将以下 Python 代码粘贴进去并 ent ...

  10. Excel单元格的日常操作

    通过右键选择插入来移动单元格 灵活的运用"整行" 与 "整列" 选中区域之后 通过点击区域边框进行移动 按住shift之后框会变成线 更容易拖动 按住ctrl拖 ...