https://blog.csdn.net/nuomizhende45/article/details/81158383
1.ClassPathXmlApplicationContext的refresh方法
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配置中加载,从注解中加载。
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,
1.12 解析出了一个beanDefinition,此时只是一个空壳,包含一些类信息,后面继续解析其他标签
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成功后,发送注册事件