第一步就是执行构造器,然后扫描配置信息
Ioc初始化首先要执行this()构造器,构造器中初始化了AnnotatedBeanDefinitionReader()读取器用来扫描注解类,ClassPathBeanDefinitionScanner()用来扫描配置类,然后扫描配置类或者加载配置信息
然后在refresh方法中执行扩展功能(重点)
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新容器 获取系统时间 ,把active设置为true close设置为false
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
//子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//调用所有注册的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//为BeanFactory注册BeanPost事件处理器.
//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//初始化信息源,和国际化相关.
initMessageSource();
// Initialize event multicaster for this context.
//初始化容器事件传播器.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//调用子类的某些特殊Bean初始化方法
onRefresh();
// Check for listener beans and register them.
//为事件传播器注册事件监听器.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//初始化所有剩余的单例Bean.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
//销毁已创建的单例Bean
destroyBeans();
// Reset 'active' flag.
//取消refresh操作,重置容器的同步标识.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
概括
下面概括一下ClassPathXmlApplicationContext初始化的步骤,并从中解释一下它为我们提供的功能
- 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证
在某种情况下项目的使用需要读取某些系统变量,而这个变量的设置很可能会影响着系统的正确性,那么ClassPathXmlApplicationContext为我们提供的这个准备函数就显得非常必要,它可以在spring启动的时候提前对必要的变量进行存在性验证
- 初始化BeanFactory,并进行XML文件的读取
之前有提到过ClassPathXmlApplicationContext包含着BeanFactory所提供的一切特征,那么在这一步骤中将会复用beanFactory中的配置文件读取解析及其它功能,这一步之后,ClassPathXmlApplicationContext实际上就已经包含了BeanFactory所提供的功能,也就是可以进行bean的提取等基础操作了.
- 对BeanFactory进行各种功能填充
@Qualifier与@Autowired正是在这一步增加的支持。
- 子类覆盖方法做额外的处理
提供一个空函数postProcessBeanFactory来方便程序员在业务上做进一步的处理。
- 激活各种BeanFactory处理器
- 注册拦截bean创建的bean处理器,这里只是注册,真正的调用是在getBean的时候
- 为上下文初始化Message源,对不同语言的消息体进行国际化处理。
- 初始化应用消息广播器,并放入“applicationEventMulticaster”bean中。
- 留给子类来初始化其他的bean
- 在所有注册的bean中查找listener bean ,注册到消息广播器中。
- 初始化剩下的单实例的bean
- 完成刷新过程通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人.
详细分析
1. prepareRefresh准备刷新的上下文环境
prepareRefresh函数主要是做一些准备工作,例如对系统属性及环境变量的初始化和验证
2.加载beanFactory
ConfigurableListableBeanFactory beanFactory=obtainFreshBeanFactory();
obtainFreshBeanFactory()方法从字面理解就是获取BeanFactory。因为ApplicationContext是对beanFactory的扩展,那么obtainFreshBeanFactory()正式实现BeanFactory的地方,经过这个函数之后ApplicationContext就拥有了BeanFactory的全部功能.
详细步骤如下:
(1)创建DefaultListableBeanFactory,它是容器的基础,必须要先进行实例化
(2)指定序列号id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
(3)定制beanFactory对象,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及是否允许循环依赖以及设置@Autowired和@Qualifier的注解解析器AualifierAnnotationAutowiredCandidateResolver
(4)加载beanDefinition信息
(5)使用全局变量记录BeanFactory实例,因为DefaultListableBeanFactory类型的变量beanFactory是函数内的局部变量,所以要使用全局变量记录解析内容.
3.prepareBeanFactory(beanFactory)
对beanFactory进行各种功能填充
- 增加对SpEL语言的支持
- 增加对属性编辑器的支持
- 增加对一些内置类,比如EnvironmentAware,MessageSourceAware的信息注入.
- 设置了依赖功能可以忽略的接口
- 注册了一些固定依赖的属性
- 增加AspectJ的支持
- 将相关环境变量及属性注册以单例模式注册.
4.postProcessBeanFactory(beanFactory)
空方法,交由子类覆盖方法做额外的处理
5.invokeBeanFactoryPostProcessors(beanFactory)
激活各种BeanFactory处理器
对于BeanFactoryPostProcessor的处理主要分为两种情况,一个是对于BeanDefinitionRegistry类的特殊处理,另一种是对普通的BeanFactoryPostProcessor进行处理。而对于每种情况都要考虑硬编码注入注册的后处理器以及通过配置注入的后处理器
对于BeanDefinitionRegistry类型的处理类的处理主要包括以下内容
(1)对于硬编码注册的后置处理器的处理,主要是通过AbstractApplicationContext中的添加处理器方法addBeanFactoryPostProcessor进行添加。添加的后处理器会存放在beanFactoryPostProcessors中,而在处理BeanFactoryPostProcesor时候会先检测beanFactoryPostProcessors是否有数据。当然,BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,不但有BeanFactoryPostProcessor的特性,同时还有自己的个性化方法,也需要在此进行调用。所以,这里需要从BeanFactoryPostProcessors中挑出BeanDefinitionRegistryPostProcessor的后置处理器,并调用其postProcessBeanDefinitionRegistry方法
(2)记录后置处理器主要使用了三个List来完成
- registryPostProcessors:记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor类型的处理器
- regularPostProcessors:记录通过硬编码方式注册的BeanFactoryPostProcessor类型的处理器
- registryPostProcessorBeans:记录通过配置文件方式注册的BeanDefinitionRegistryPostProcessor类型的处理器
(3)对以上记录的List中的后置处理器进行统一调用BeanFactoryPostProcessor的postProcessBeanFactory方法
(4)对beanFactoryPostProcessors中非BeanDefinitionRegistryPostProcessor类型的后置处理器进行统一的BeanFactoryPostProcessor的postProcessBeanFactory方法的调用
(5)普通beanFactory的处理
BeanDefinitionRegistryPostProcessor只对BeanDefinitionRegistry类型的ConfigurableListableBeanFactory有效,所以如果判断所示的beanFactory并不是BeanDefinitionRegistry,那么便可以忽略BeanDefinitionRegistryPostProcesser,而直接处理beanFactoryPostProcessor,当然获取的方式和上边相同
对于使用硬编码的方式手动添加的后置处理器是不需要做任何排序的,但是在配置文件中读取的处理器,spring并不保证读取的顺序。所以,为了保证用户的调用顺序的要求,spring对于后置处理器的调用支持按照PriorityOrdered或者Ordered的顺序调用。
6.registerBeanPostProcessors(beanFactory)
注册拦截bean创建的bean处理器,这里只是注册,真正的调用是在getBean时候.
对于BeanPostProcessors的处理和BeanFactoryPostProcessor的处理极为相似,但是又有一些不同的地方。对于BeanFactoryPostProcessor的处理要分为两种情况,一种是通过硬编码方式的处理,另一种是通过配置文件方式的处理。而在BeanPostProcess中只考虑了对于配置文件方式的处理。这是因为对于BeanFactoryPostProcessor的处理,不但要实现注册功能,还要实现对后置处理器的调用操作,所以需要再入配置中的定义,并进行调用;而对于BeanPostProcessor并不需要马上调用,再说,硬编码的方式实现的功能是将后置处理器提取并调用,这里并不需要调用,所以不需要考虑硬编码的方式,这里的功能只需要将配置文件的BeanPostProcesor提取出来并注册到BeanFactory中就可以了
而且对于BeanFacoty的注册,并不是直接注册就可以的。在spring中支持对于BeanPostProcessor的排序,比如根据PriorityOrdered进行排序,根据Ordered进行排序或者无序,而spring在BeanPostProcessor的激活顺序的时候也会考虑对于顺序问题而先进行排序。
7.initMessageSource()
为上下文初始化Message源,即不同语言的消息体,国际化处理。
8.initApplicationEventMulticaster()
初始化应用消息广播器,并放入applicationEventMulticaster 这个bean中
对于ApplicationEventMulticaster的初始化无非考虑两种情况
- 如果用户自定义了事件广播器,就使用用户自定义的事件广播器
- 如果用户没有自定义事件广播器,那么是有个默认的ApplicationEventMulticaster
当产生Spring事件的时候会默认使用SimpleApplicationEventMulticaster的multicastEvent来广播事件,遍历所有的监听器,并使用监听器中的onApplicationEvent方法来进行监听器的处理。而对于每一个监听器都能获取到产生的事件,但是是否进行处理则由事件监听器来决定。
9.onRefresh()
留给子类用来初始化其他的Bean
10.regisrerListeners()
注册监听器,将通过硬编码方式和配置文件方式注册的监听器加入到广播器中,在所有注册的bean中查找Listener bean,注册到消息广播器中
11.finishBeanFactoryInitialization(beanFactory)
初始化剩下的单实例的Bean(非惰性的),完成BeanFactory的初始化工作,其中包括ConversionService的设置,配置冻结以及非延迟加载bean的初始化工作。
12.finishRefresh()
完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
- initLifecycleProcessor
当ApplicationContext启动或者停止时,它会通过LifecycyleProcessro来与所有声明的bean的周期做状态更新,而在LifecycleProcessor的使用前首先需要进行初始化,如果容器中有就从容器中获取,如果没有就新建一个默认的生命周期处理器然后注册到容器中
- OnRefresh
注意不要和上边的方法搞混淆了,这个是生命周期处理器的Onrefresh方法,作用是启动所有的实现了Lifecycle接口的bean
- publishEvent
当完成ApplicationContext初始化的时候,要通过Spring中的时间发布机制来发出ContextRefreshEvent事件,以保证对应的监听器可以做进一步的逻辑处理。