​https://blog.csdn.net/nuomizhende45/article/details/81158383​

1.ClassPathXmlApplicationContext的refresh方法

Spring 源码复习 01 IOC 个人笔记 01_启动时间


refresh为IOC核心函数,具体分为如下的十二个步骤:


一、prepareRefresh : 准备工作,记录下容器的启动时间,标记已启动状态,解析配置文件中占位符


二、 beanFactory :创建一个beanFactory


三、prepareBeanFactory: 设置BeanFactory的类加载器,添加BeanPostProcessor,手动注册几个特殊的bean


四、postProcessBeanFactory(beanFactory) : 在bean都加载,注册完成了,可以自定义一些实现


五、invokeBeanFactoryPostProcessors(beanFactory) : 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法


六、registerBeanPostProcessors(beanFactory) : BeanFactoryPostProcessor前面已经完成,此时开始注册BeanPostProcessor的实现类,此接口2个方法,postProcessBeforeInitialization 在bean初始化之前执行;postProcessAfterInitialization在bean初始化之后执行。


七、initMessageSource : 国际化


八、initApplicationEventMulticaster: 初始化当前ApplicationContext事件的广播器


九、onRefresh : 在这里初始化一些特殊的bean,在初始化singleton beans之前


十、registerListeners: 注册事件监听器,监听器实现ApplicationListener接口


十一、finishBeanFactoryInitialization: 初始化所有的singleton beans,不包括懒加载lazy-init的bean


十二、finishRefresh:最后,广播事件,ApplicationContext初始化完成


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


一、prepareRefresh : 刷新容器前做一些准备工作


     1.设置active属性为true,设置启动时间


     2. 在context的环境中,初始化属性来源propertySources


     3. 校验配置文件,调用getEnvironment().validateRequiredProperties();


     4. 初始化预刷新pre-refresh 的监听器 ApplicationtionListeners


     5. 初始化earlyApplicationEvents


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


二、创建BeanFactory 核心


ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


   1. 关闭旧的beanFactory(如果有), 创建新的beanFactory,加载bean定义也就是 beanDefinitions


     1.1 创建一个 DefaultListableBeanFactory  


     1.2  BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。  


    1.3 customizeBeanFactory:就是配置是否允许 BeanDefinition 覆盖、是否允许循环引用。


    1.4 最核心的加载bean方法 loadBeanDefinitions(beanFactory)  :根据配置,加载bean,放入到beanFactory中


          分成从xml配置中加载,从注解中加载。


Spring 源码复习 01 IOC 个人笔记 01_配置文件_02


Spring 源码复习 01 IOC 个人笔记 01_加载_03


Spring 源码复习 01 IOC 个人笔记 01_xml_04


  1.8 开始解析xml文档 :先解析默认的xml标签


        parseDefaultElement(ele, delegate) 代表解析的节点是 <import/>、<alias/>、<bean/>、<beans/> 这几个


   1.9 再继续解析自定义的标签


        如我们经常会使用到的 <mvc/>、<task/>、<context/>、<aop/>等。


   1.10 继续1.8,重点先看解析<bean/> 标签,解析其中的各种属性,包括id,name,class,scope,properties等


   1.11  AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement,


Spring 源码复习 01 IOC 个人笔记 01_配置文件_05


1.12 解析出了一个beanDefinition,此时只是一个空壳,包含一些类信息,后面继续解析其他标签

Spring 源码复习 01 IOC 个人笔记 01_加载_06

​1.13 至此,解析出一个BeanDefinitionHolder实例


1.14 解析完成后,就开始注册beanDefinition


      BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());


1.15 先根据入参beanName,从beanDefinitionMap获取bean,如果有,代表注册过


1.16 判断当前配置,如果不允许覆盖,那么就直接抛出异常,因为已经注册过了


1.17 如果允许覆盖,就用新的bean覆盖旧的bean,


   this.beanDefinitionMap.put(beanName, beanDefinition);


1.18 注册bean成功后,发送注册事件