当前位置:   article > 正文

Spring IOC的启动流程(Spring bean对象的创建过程),从理论到源码,一步分析到位_spring ioc启动过程

spring ioc启动过程

在这里插入图片描述
    这里new了一个ClassPathXmlApplicationContext对象,这其实是最简单的创建IOC容器的方法,我们点进去。

在这里插入图片描述
    这是它的构造方法,它重载了其他构造方法,点this,可以看到:
在这里插入图片描述
    在这个方法中,我们可以看到他调用了一个refresh()刷新的方法,这个刷新就是IOC容器的刷新开启方法,我们再点进去。

类:AbstractApplicationContext
在这里插入图片描述
    可以一次正常的流程,他一共调用了12个方法来启动IOC容器。

第一个方法:this.prepareRefresh();

在这里插入图片描述

    prepareRefresh()方法主要的作用就是在容器刷新前做准备工作:

  1. 设置容器的启动时间
  2. 设置一些状态标识符
  3. 初始化占位符属性资源
  4. 创建环境对象,校验必填属性是否可解析
  5. 初始化一些 成员变量,如earlyApplicationListnenrsearlyApplicationEvents

在这里插入图片描述

第二个方法:obtainFreshBeanFactory();

    obtainFreshBeanFactory();方法的主要作用是创建一个DefaultListableBeanFactory工厂,给bean工厂设置一个属性,加载配置文件信息,封装bean定义信息。包扫描也是扫描到这个包下面的bean,然后封装成bean定义信息,并设置到DefaultListableBeanFactory的成员属性中。

  1. 创建bean工厂类型是DefaultListableBeanFactory
  2. 设置bean工厂的序列号ID
  3. 初始化bean工厂,设置一些属性,如allowBeanDefinitionOverridingallowCircularReferences
  4. 加载bean定义信息,初始化BeanDefinitionReader读取器,将配置文件转化为输入流对象,通过SAX解析XML文件中的默认标签及自定义标签内容,封装成BeanDefinition(也就是Bean的定义信息),注册到DefaultListableBeanFactory的beanDefinitionMap的属性中。
第三个方法:prepareBeanFactory(beanFactory);

    prepareBeanFactory(beanFactory);的主要作用是设置bean工厂的一些属性,如添加一些BeanPostProcessor增强器。

  1. 设置bean的类加载器信息。
  2. 添加一些BeanPostProcessor增强器。
  3. 忽略一些接口的自带装配依赖。
  4. 注册一些bean对象到容器中,如environmentsystemProperties
第四个方法:postProcessBeanFactory(beanFactory);

    postProcessBeanFactory(beanFactory);它是一个模板方法,主要是为了留给子类扩展实现。

  1. 允许子类修改、扩展bean工厂。
第五个方法:invokeBeanFactoryPostProcessors(beanFactory);

    invokeBeanFactoryPostProcessors(beanFactory);方法的主要作用是执行BeanFactoryPostProcessor的后置处理器的postProcessBeanFactory()增强方法。

  1. 调用实现了PrioityOrdered接口的BeanDefinitionRegistryPostProcessoes
  2. 调用实现了Ordered接口的BeanDefinitionRegistryPostProcessoes
  3. 其它BeanDefinitionRegistryPostProcessoes
  4. 调用实现了PrioityOrdered接口的BeanFactoryPostProcessor
  5. 调用实现了Ordered接口的BeanFactoryPostProcessor
  6. 其它BeanFactoryPostProcessor
第六个方法:registerBeanPostProcessors(beanFactory);

    registerBeanPostProcessors(beanFactory);方法的主要作用是注册BeanPostProcessor后置增强器,这里只是注册,真正执行是在初始化阶段的前后执行。

  1. 注册实现了PrioityOrdered接口的BeanPostProcessor
  2. 注册实现了Ordered接口的BeanPostProcessor
  3. 注册其它BeanPostProcessor
第七个方法:initMessageSource();

    initMessageSource();方法的主要作用是初始化MessageSource,国际化处理。

第八个方法:initApplicationEventMulticaster();

    initApplicationEventMulticaster();方法的主要作用是初始化应用事件多播器。

  1. 它首先会判断我们的bean工厂中是否存在applicationEventMulticaster
  2. 如果存在的话直接获取。
  3. 如果不存在,直接创建一个新的SimpleApplicationEventMulticaster,并注册到IOC容器中。
第九个方法:onRefresh();

    onRefresh();方法也是一个模板方法,留给子类扩展实现。

  1. 它是在单例化对象实例之前,允许子类做一下扩展。
第十个方法:registerListeners();

    registerListeners();方法的主要作用是注册一些监听器。

  1. 实际上就是往applicationEventMulticaster事件多播器注册一些列的监听器
第十一个方法:finishBeanFactoryInitialization(beanFactory);

    finishBeanFactoryInitialization(beanFactory);最重要的一个方法,主要是完成完成非懒加载的单例bean对象的实例化,包括反射创建bean对象、属性填充、循环依赖处理、bean的初始化等操作。

  1. 循环遍历之前解析的BeanDefinition定义信息。
  2. 通过反射创建bean对象。
  3. bean的属性填充。
  4. 调用Aware接口相关方法,如BeanNameWare的setBeanName方法BeanFactoryAware的setBeanFactory方法等。
  5. 执行BeanPostProcessor的后置处理器的postProcessBeforeInitialization()方法的前置增强方法。
  6. 执行InitializingBean的afterPropertiesSet()方法。
  7. 执行自定义的初始化方法,如init-method等。
  8. 执行BeanPostProcessor的postProcessAfterInitialization()后置增强方法。
  9. 执行DisposalbeBean的destory()销毁方法。后面这两个方法是销毁是才使用的
  10. 执行自定义的销毁方法,如destory-method等 。
第十二个方法:finishRefresh();

    finishRefresh();方法的主要作用是容器刷新完成后的一些处理工作。

  1. 一些资源的清理
  2. 初始化生命周期处理,调用onRefresh()刷新方法。
  3. 发布容器已刷新事件。

总结

    第一步 首先会执行一些容器刷新前的准备工作,比如设置容器失效时间、一些状态标志位等。

    第二步 创建容器对象,其实就是实例化DefaultListableBeanFactory对象,这一步包含了bean定义信息的解析,解析后的属性都封装到了DefaultListableBeanFactory的成员属性中。

    第三步 准备bean工厂,实际上就是设置beanFactory的一些属性

     第四步 Spring提供了postProcessBeanFactory()方法给我们去扩展,例如我们可以注册一些特殊的BeanPostProcessor后置处理器等操作

    第五步 执行BeanFactoryPostProcessor后置处理器的postProcessBeanFactory()增强方法,使用三个不同的集合分别存放实现了PriorityOrdered接口Ordered接口普通的BeanFactoryPostProcessor,经过排序后,执行这个后置处理器的回调方法postProcessBeanFactory()

    第六步 注册BeanPostProcessor后置处理器。这里不会执行 BeanPostProcessor对应的增强方法。同样的,使用三个不同的集合分别存放实现了PriorityOrdered接口Ordered接口普通的BeanFactoryPostProcessor。依次调用beanFactory.addBeanPostProcessor(postProcessor)方法往bean工厂中添加BeanPostProcess。

    第七步 为上下文初始化MessageSource,即国际化处理。

    第八步 初始化事件多播器,即ApplicationEventMulticaster,为后面的事件发布-监听做准备。

    第九步 提供一个模板方法onRefresh(),留给子类初始化其他的bean。

    第十步 注册事件监听器。

    第十一步 也是最关键的一步,这里会实例化剩下的非懒加载的单例bean,Bean的生命周期也是从这里开始。
    具体一点就是说,这里会获取到之前解析的所有bean名称集合,挨个调用getBean(beanName)方法,然后经历doGetBean()createBean()doCreateBean()创建bean的流程。接着会通过反射创建出我们的bean实例对象,然后进行populateBean()属性填充。属性填充完成后,会执行bean的初始化。初始化bean的主要执行Awre接口方法、执行初始化方法、回调BeanPostProcessor后置增强器的方法等。、

    第十二步 完成上下文的刷新工作,如清除一些缓存、发布容器刷新的完成的事件等。

源码流程:

1.

在这里插入图片描述
通过new ClassPathXMLApplicationContext传入Spring的配置文件,创建出一个IOC容器。

配置文件:spring-config.xml
在这里插入图片描述
目前值配置了一个bean对象,指定了它的初始化方法以及销毁方法的方法名。还指定了为这个name属性赋值为“zhangsan”;

2.

然后来看看我们写的Student类,实现了BeanFactory接口、ApplicationContextAware接口、InitializingBeanDisposableBean接口。
在这里插入图片描述

并且也重写了对应的setApplicationContext()setBeanFactory()afterPropertiesSet()dsetroy()方法。
在这里插入图片描述

3.

然后再创建ClassPathXMLApplicationContext的代码上打上断点,然后执行。
在这里插入图片描述

4.

首先,会进入ClassPathXmlApplicationContext的构造方法。
在这里插入图片描述

它调用了一个重载的构造方法,继续进入。可以看到会继续往下执行refresh()它是IOC容器的启动的核心方法。在这里插入图片描述

5 (重点).

继续往下执行,会进入refresh()方法,正常执行会执行第一步,prepareRefresh(),也就是进入容器刷新前的准备工作。
在这里插入图片描述

继续往下执行,进入prepareRefresh()方法:
在这里插入图片描述

可以看到,这个方法实际上是设置了容器的启动时间以及一些状态标志位。
在这里插入图片描述

并且设置了初始化占位符属性源,以及获取到EnvironMent对象,并且验证重要的属性是否都放入到了环境中。
在这里插入图片描述

并且还判断了刷新前应用程序监听器集合是否为空。
如果不为空,则清空集合。
如果为空,则把监听器加入到集合中。
在这里插入图片描述
继续往下执行,第一个方法执行完毕。

6.

接下来继续执行第二个方法:obtionFreshBeanFactory();,返回值用ConfigurableListableBeanFactory对象接收。它主要工作是创建容器,并进行XML文件读取。
在这里插入图片描述

继续往下执行,我们进入obtainFreshBeanFactory()方法,接着进入refreshBeanFactory()方法,接着继续进入createListableBeanFactory()方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,直接new了一个DefaultListableBeanFactory 的bean工厂。

bean工厂创建完之后,设置了工厂的序列号ID,以及定制化Bean工厂。在这里插入图片描述

实际上是设置了两个属性的值:
在这里插入图片描述

第一个是否允许覆盖同名的不同定义的bean对象。
第二个是是否允许循环依赖。

接着执行loadBeanDefinitions(),这就是解析XML配置文件,加载Bean定义信息。接着继续往下执行
在这里插入图片描述

进入loadBeanDefinitions()。初始化了一个XMLBeanDefinitionReader 定义信息的读取器,然后设置了一些属性。
在这里插入图片描述
在这里插入图片描述

然后进入loadBeanDefinitions()方法,继续执行,可以看到configLocations也就是我们传入的XML配置文件的路径,然后通过loadBeanDfinitions()传入路径,进行加载,然后继续进入,在这里插入图片描述

这里是循环获取的,因为我们的路径可以传入多个,所以需要循环处理。
在这里插入图片描述

信息获取完后继续执行,然后再doLoadBeanDefinitions()中加载bean的定义信息。
在这里插入图片描述

经过doLoadDocument()方法之后,我们的XML配置文件就转换为document文档对象。然后我们就可以从文档对象中解析、注册bean的定义信息。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    经过otbainFreshBeanFactory()方法后,我们xml中bean的定义信息已被读取,并且被解析封装到了我们bean工厂中对应的成员变量中,我们通过beanFactory看到被解析出的所有信息。
在这里插入图片描述

7.

第二个方法执行完毕,接着继续往下走,开始执行第三个方法:
prepareBeanFactory();
在这里插入图片描述

我们进入这个方法,可以看到实际上就是设置了一些属性而已。
    比如bean的类加载器、bean的表达式解析器、属性编译器,并且添加了一些后置处理器,以及忽略了一些接口的自动装配依赖等。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8.

接下来继续往下走,执行第四个方法:postProcessBeanFactory(),这里是空的方法,主要是为了给子类去扩展的处理。
在这里插入图片描述
在这里插入图片描述
从注释中可以看到,执行到这里的时候,所有bean的定义信息已经加载完成,但是暂时还没bean被实例化,它允许我们注册特殊的后置处理器,

9.

接下来执行第五个方法:invokeBeanFactoryPostProcessors()方法。也就是执行BeanFactoryPostProcessors后置处理器的postProcessBeanFactory()增强方法。
在这里插入图片描述

我们进入这个方法,继续进入。
在这里插入图片描述
在这个方法中可以看到,分别用三个集合存放了实现了接口的后置处理器。
在这里插入图片描述

然后挨个通过isTypeMatch()判断他们依次存入的是哪个集合中
在这里插入图片描述

存放好之后,然后排序,再进入invokeBeanFactoryPostProcessors()方法,这个方法其实就是循环所有的后置处理器,然后回调postProcessBeanFactory()方法经过排序在这里插入图片描述
这就是第五个方法,主要是围绕后置处理器来进行操作。

10.

然后接着往下执行,进入第六个方法:registerBeanPostProcessors(),主要是注册bean的后置处理器BeanPostProcess, 这里还不好执行后置处理器对应的增强方法。真正调用时在bean的初初始化之前、初始化之后。进入这个方法
在这里插入图片描述
在这里插入图片描述
很长一大段:
在这里插入图片描述

它的处理过程与BeanFactoryPostProcessors类似,也是通过三个集合分别存放不同的后置处理器,然后经过排序,最后调用registerBeanPostProcess(),这里会调用beanFactory的addBeanPostProcessor()把这个后置处理器添加到我们bean工厂中。也就是完成了后置处理器的注册功能。在这里插入图片描述
在这里插入图片描述

11.

接着继续往下走,第七个方法:initMessageSource(),为上下文初始化MessageSource,即不同语言的消息体。
在这里插入图片描述

我们进入这个方法。
在这里插入图片描述
首先会获取到当前的bean工厂,然后判断bean工厂中是否存在id为messageSource的bean。在这里插入图片描述

如果存在的话,则直接获取到
在这里插入图片描述
如果不存在的话,则会新建一个DelegatingMessageSource,作为bean,并且id是messageSource,然后注册到bean工厂中。
在这里插入图片描述

12.

接下来执行第八个方法:initApplicationEventMulticaster(),初始化事件多播器
在这里插入图片描述
它的处理过程与MessageSource()类似,
在这里插入图片描述

首先判断bean工厂中是否有ID为ApplicationEventMulticaster的bean。如果有,则直接用getBean()来获取。
在这里插入图片描述
如果不存在的话,则会new一个SimpleApplicationEventMutilcaster事件多播器,并注入到bean工厂中。
在这里插入图片描述

13.

接着继续往下点,执行第九个方法onRefersh(),这也是一个模板方法,留给子类初始化其他的bean。从注释上看,他允许我们执行一些特殊bean的初始化,在单例bean对象初始化之前。
在这里插入图片描述

在这里插入图片描述

14.

接着继续执行第十个方法:registerListeners(),注册监听器
在这里插入图片描述

点击进入方法里。
在这里插入图片描述

首先,它这里会获取到硬编码方式注册的ApplicationListener,然后把他添加到事件多播器中。
在这里插入图片描述

其次会从bean工厂中找出所有实现了ApplicationListener接口的bean,然后循环添加到事件多播器中。
在这里插入图片描述

最后,它会判断如果早期应用发布事件,它会发布早期的事件到响应的监听器中, 并将earlyApplicationEvents早期事件置空。
在这里插入图片描述
仔细看,它发布事件就是调用我们前面初始化好的ApplicationEventMutilcaster,然后调用它的mutilcastEvent()发布事件。

15.

然后执行第十一个方法finishBeanFactoryInitialization(beanFactory) 他是refresh()中最重要的一个方法,实例化所有剩下的非懒加载的单例Bean。
在这里插入图片描述

进入这个方法
在这里插入图片描述

其他都是一些中规中矩的代码,最后一行尤为重要:实例化所有剩余的非懒加载单例bean。
在这里插入图片描述

我们继续进入preInstantiateSingletons(),(可以看到增强for循环的beanNames只有一个Students),然后它会循环所有的beanName,挨个调用getBean()方法
在这里插入图片描述
在这里插入图片描述
这里会执行getBean(beanNane),然后进入
在这里插入图片描述
在这里插入图片描述
会执行doGetBean()

这里会执行createBean(),创建bean对象,进入这个方法。
在这里插入图片描述

执行doCreateBean(),真正创建bean的方法,
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们继续执行:
bean实例化完成后会进行属性填充,对bean的各个属性值进行注入,可以存在其他依赖bean的属性,则会递归初始依赖的bean。
在这里插入图片描述

属性填充完后会初始bean,调用initialBean()
在这里插入图片描述

我们进入,首先会执行Aware接口的invokeAwareMethods()方法。这是因为Student实现了BeanFactoryAware接口,所有这里它会回调这个类的setBeanFactory()方法。
在这里插入图片描述
在这里插入图片描述

Aware接口执行完后,会执行我们BeanPostProcessor后置处理器的前置处理方法,也就是回调postProcessBeforeInitialization(),点击进入。
在这里插入图片描述

通过这里我们可以看到它回调的是我们的前置增强方法。
在这里插入图片描述

前置回调方法处理完后,会调用invokeInitMethods()执行初始化方法,我们进入。
在这里插入图片描述

首先会判断这个bean是否试下了InitializingBean接口。
在这里插入图片描述

我们的Student是实现了InitializingBean的,所有它会回调我们的afterPropertiesSet()方法,执行一些初始化工作
在这里插入图片描述

接着就是调用我们用户的自定义初始化方法。
在这里插入图片描述

初始化方法完成后,通过下面这个方法可以执行后置处理器的后置处理方法。点击方法内部,他是循环所有的BeanPostProcessor后置增强器,然后挨个调用后置增强方法。
在这里插入图片描述
在这里插入图片描述

初始化方法完成后,这个bean就已经创建成功了,接着它会存入到我们的缓存中。
在这里插入图片描述

这就是第十一个方法,实例化所有的非懒加载单例Bean,内容很多,但也很重要。

16.

最后第十二个方法,finishRefresh(),它是完成上下文的刷新工作。
在这里插入图片描述
在这里插入图片描述

主要就是清除一些缓存,初始化生命周期处理器,以及发布容器刷新完成的一些事件等。
在这里插入图片描述

通过这些步骤,一个完整的bean对象就被创建了出来,也是IOC容器的启动过程

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/241505
推荐阅读
相关标签
  

闽ICP备14008679号