前言

本次对于Spring的IOC容器的创建过程是基于其源码进行研究分析的,主要涉及BeanFactory的创建过程,Bean的解析与注册过程,Bean实例化的过程以及诸如ClassPathXmlApplicationContext的IOC构建过程。

IOC容器创建过程

在Spring中,三大核心组件Context、Bean以及Core中,Context将Bean和Core结合起来了,从而使得三大核心组件相互作用,共同构建整个Spring的基础。在Spring中,ApplicationContext的子类AbstractApplicationContext的refresh()是构建Bean的入口点,它设定了创建IOC的模板方法。子类创建IOC最终都会委派到该方法进行创建的。

AbstractApplicationContext的refresh()源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public void refresh() throws BeansException,
IllegalStateException {
synchronized (this.startupShutdownMonitor)
{
   //
准备上下文用于刷新
   prepareRefresh();
   //
创建BeanFactory,Bean定义的解析与注册
   ConfigurableListableBeanFactory
beanFactory =     obtainFreshBeanFactory();
  //
为该上下文配置已经生成的BeanFactory
  prepareBeanFactory(beanFactory);
    try {
    //可以调用用户自定义的BeanFactory来对已经生成的BeanFactory进行修改
    postProcessBeanFactory(beanFactory);
    invokeBeanFactoryPostProcessors(beanFactory);
    //可以对以后再创建Bean实例对象添加一些自定义操作
    registerBeanPostProcessors(beanFactory);
    //初始化信息源
    initMessageSource();
    //初始化事件
    initApplicationEventMulticaster();
    //初始化在特定上下文中的其它特殊Bean
    onRefresh();
    registerListeners();
    //Bean的真正实例化,创建非懒惰性的单例Bean
    finishBeanFactoryInitialization(beanFactory);
    finishRefresh();
   }catch (BeansException
ex) {
    destroyBeans();
    cancelRefresh(ex);
    throw ex;
   }
}

整个方法代码使用的就是模板方式设计模式,工厂方法模式等,定义了整个BeanFactory构建过程。构建BeanFactory,以便于产生所需要的Bean对象;注册可能感兴趣的事件;创建Bean实例对象;触发被监听的事件。IOC容器就是一个Context组合另外两个核心组件而形成的Bean的关系网,是Bean的大容器

在解析IOC容器的创建过程中,以下面两行代码为原型,来穿插着解析该IOC的创建过程。这是一种常见的IOC容器的创建过程,仅仅通过new一个ClassPathXmlApplicationContext就完成了IOC创建。

1
2
ApplicationContext
ctx = 
new ClassPathXmlApplicationContext("beans.xml");
    UserService
service = ctx.getBean(
"ser",UserService.class);

ClassPathXmlApplicationContext的继承关系如下

当我们new一个ClassPathXmlApplicationContext,为其传递一个bean配置文件的地址,其最终调用的构造器如下:

1
2
3
4
5
6
7
8
9
10
11
public ClassPathXmlApplicationContext(String[]
configLocations, 
boolean refresh,
ApplicationContext parent)
{
        super(parent);
        //设置配置文件的位置configLocations
    setConfigLocations(configLocations);
    if (refresh)
{
        //这里就是调用了父类AbstractApplicationContext的refresh
        //也证实了refresh是构建IOC的入口点
    refresh();
    }
}

从源代码可以看出,第一句,最终会调用继承关系中的AbstractApplicationContext构造器,具体做的工作就是返回一个PathMatchingResourcePatternResolver。

第二句,设置配置文件的位置,调用父类AbstractRefreshableConfigApplicationContext的方法,设置configLocations的值。利用这种构造器创建,并没有设置其属性configResources的值,则为null。(这个在下面讲IOC创建的地方需要用到)。

第三句,在该构造器中调用了父类AbstractApplicationContext的refresh方法,从而进行IOC的真正创建了。

BeanFactory创建:

BeanFactory创建是在obtainFreshBeanFactory方法中完成的。在该方法中,会调用子类实现了refreshBeanFactory的方法,刷新子类,如果BeanFactory存在则刷新,如果不存在就创建一个新的BeanFactory。最终默认的创建BeanFactory就是由DefaultListableBeanFactory来完成的。

这是一个BeanFactory创建的时序图,在该时序图中包含了BeanFactory创建的过程,还有Bean定义的解析、加载以及注册过程,关于Bean定义的解析与加载注册过程,会在下面以详细的时序图来解释的。这里只是refresh()方法中,调用refreshBeanFactory()来构建BeanFactory的标准初始化过程。我们ClassPathXmlApplicationContext的BeanFactory就是遵循这样的构造过程。

Bean解析注册过程:

在上面的时序图中,最右边可以看到对Bean的定义进行加载与解析和注册处理,

在AbstractXmlApplicationContext中调用loadBeanDefinitions,这里最终是交给XmlBeanDefinitionReader来加载指定的bean定义。AbstractXmlApplicationContext类的loadBeanDefinitions()方法源码如下:

1
2
3
4
5
6
7
8
9
10
protected void loadBeanDefinitions(XmlBeanDefinitionReader
reader) 
throws BeansException,
IOException {
        Resource[]
configResources = getConfigResources();
        if (configResources
!= 
null)
{
            reader.loadBeanDefinitions(configResources);
        }
        String[]
configLocations = getConfigLocations();
        if (configLocations
!= 
null)
{
            reader.loadBeanDefinitions(configLocations);
        }
    }

这个方法就是根据指定的XmlBeanDefinitionReader来加载我们的Bean定义,并且最其进行解析和注册处理。

在这里,一般只会执行其中的一个if语句,这里我们的ClassPathXmlApplicationContext,前面已经说过,new的过程只设置了configLocations值,并没有设置configResources属性值,则就会直接执行第二个if语句。这里就会调用AbstractBeanDefinitionReader的一个重载方法loadBeanDefinitions方法,这个最终是调用子类XmlBeanDefinitionReader的loadBeanDefinitions()

具体的标准Bean解析注册过程如下:

其它初始化与准备过程:

在BeanFactory创建完成后,我们定义的Bean仅仅是已经被解析和注册了,实际上还没真正的创建他们的实例对象。当obtainFreshBeanFactory()方法返回后,就会为该上下文配置刚刚已经生成的BeanFactory,我们要想扩展Spring的IOC容器,则就可以在下面的三个代码处进行自定义操作

1
2
3
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);

前两句主要就是当一个BeanFactory创建完成后,我们可以调用自定义的BeanFactory,对已经创建的配置信息进行修改。最后一句就是在以后的Bean的实例化过程中,可以定义一些自定义操作。

接下来就是就是初始化上下文的信息源,应用程序事件,其他特殊bean。

Bean实例对象创建过程:

在该refresh中,最后会调用finishBeanFactoryInitialization来完成Bean的实例对象创建过程。具体的Bean创建时序图如下:

在Bean的创建过程,有个特殊的FactoryBean,这是个特殊的Bean他是个工厂Bean,可以产生Bean的Bean,这里的产生Bean是指 Bean的实例,如果一个类继承FactoryBean用户可以自己定义产生实例对象的方法只要实现他的getObject方法。在Spring内部这个Bean的实例对象是FactoryBean,通过调用这个对象的getObject方 法就能获取用户自定义产生的对象,从而为Spring提供了很好的扩展性。Spring获取FactoryBean本身的对象是在前面加上&来完成的。

在我们的示例代码的第二行,当使用getBean的时候获取Bean的时候具体流程如下:

1,它会调用抽象方法getBeanFactory()

2,最终调用AbstractRefreshableApplicationContext的getBeanFactory,是final的方法。

本文出自 “在云端的追梦” 博客,请务必保留此出处http://computerdragon.blog.51cto.com/6235984/1244016

Spring的IOC容器创建过程深入剖析的更多相关文章

  1. Spring之IOC容器初始化过程

    Ioc容器的初始化是由refresh()方法来启动的,这个方法标志着Ioc容器的正式启动. 具体来说这个启动过程包括三个基本过程: 1.BeanDifinition的Resource定位 2.Bean ...

  2. Spring Boot IoC 容器初始化过程

    1. 加载 ApplicationContextInializer & ApplicationListener 2. 初始化环境 ConfigurableEnvironment & 加 ...

  3. SpringMVC——DispatcherServlet的IoC容器(Web应用的IoC容器的子容器)创建过程

    在上一篇<Spring--Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)>中说到了Web应用中的IoC容器创建过程.这一篇主要讲Sprin ...

  4. Spring IOC容器创建bean过程浅析

    1. 背景 Spring框架本身非常庞大,源码阅读可以从Spring IOC容器的实现开始一点点了解.然而即便是IOC容器,代码仍然是非常多,短时间内全部精读完并不现实 本文分析比较浅,而完整的IOC ...

  5. Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)

    基于Spring-4.3.7.RELEASE Spring的配置不仅仅局限在XML文件,同样也可以使用Java代码来配置.在这里我使用XML配置文件的方式来粗略地讲讲WebApplicationCon ...

  6. spring的启动过程就是创建ioc容器的过程

    1. spring简介 spring的最基本的功能就是创建对象及管理这些对象之间的依赖关系,实现低耦合.高内聚.还提供像通用日志记录.性能统计.安全控制.异常处理等面向切面的能力,还能帮我们管理最头疼 ...

  7. Spring IoC容器初始化过程学习

    IoC容器是什么?IoC文英全称Inversion of Control,即控制反转,我么可以这么理解IoC容器: 把某些业务对象的的控制权交给一个平台或者框架来同一管理,这个同一管理的平台可以称为I ...

  8. Spring源码解析 – AnnotationConfigApplicationContext容器创建过程

    Spring在BeanFactory基础上提供了一些列具体容器的实现,其中AnnotationConfigApplicationContext是一个用来管理注解bean的容器,从AnnotationC ...

  9. 02.Spring Ioc 容器 - 创建

    基本概念 Spring IoC 容器负责 Bean 创建.以及其生命周期的管理等.想要使用 IoC容器的前提是创建该容器. 创建 Spring IoC 容器大致有两种: 在应用程序中创建. 在 WEB ...

  10. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

随机推荐

  1. Docker的数据卷与数据卷容器操作

    一.数据卷 数据卷(Data Volumes)是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount动作. 数据卷可以提供很多有用的特性: 数据卷可以在容器之 ...

  2. FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP

    ​对各高校即将毕业的学子来说,毕业设计算是在大学里的最后一个大作业.特别是软件.计算机.电子等相关专业,毕业设计非常讲究实操,往往要求实现一个实用的.可用的.易用的软件系统或手机APP. 不管是软件还 ...

  3. 一场 Kafka CRC 异常引发的血案

    一.问题概述 客户的生产环境突然在近期间歇式的收到了Kafka CRC的相关异常,异常内容如下 Record batch for partition skywalking-traces-0 at of ...

  4. c# RSA加密解密,与java代码互通问题

    RSA加密解密原本是公开算法,但是和一个java的小伙伴对接却出现了点问题,现在记录一下 首先,RSA的公钥私钥,有2种: 1.pem格式. 2.xml格式. 文章底部有pem格式和对应的xml样本数 ...

  5. JavaScript Library – YouTube Embedded、YouTube Player API、YouTube Data API

    YouTube Embed Video 参考: Embed videos & playlists 它和 Google Maps Embed 类似,是通过 iframe 完成的. <ifr ...

  6. DOM – Web Animation API

    前言 以前写过相关的文章 angular2 学习笔记 ( animation 动画 ).但在项目种很少用到 Web Animation. 体会不到它的精髓,目前的感觉是,它对比 CSS Animati ...

  7. foobar2000 v1.6.12 汉化版(更新于2022.10.16)

    foobar2000 v1.6.12 汉化版 -----------------------[软件截图]---------------------- -----------------------[软 ...

  8. 利用cv2.dilate对图像进行膨胀

    cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))介绍,请看这个博客.我简要说一下cv2.getStructuringElement,可用于构造一个特定大 ...

  9. Pytorch 基于加权平滑过渡的无缝拼接

    基于加权平滑过渡的无缝拼接 背景 在做照片数字人视频生成的时候,为了达到快速响应实时播放的需求,即视频的生成速度 必须小于 音频的播放速度. 因此,我们截取了一部分较小的可动区域进行推理生成,然后把生 ...

  10. element表单校验 【登录】

    async btnOK () { // 1. 表单校验 (调用表单的校验方法获取校验结果) // this.$refs.formRef.validate(function (valid) { // c ...