在前一篇文章Spring探秘2:ApplicationContext启动流程中提到了Spring容器启动的最后一步是refresh,即配置的刷新,这是容器启动过程中一个核心的步骤,实现了启动容器的主要的功能。本文会简单介绍一下AbstractApplicationContext#refresh()方法的流程,其中涉及到的比较复杂的过程还需要另外详细分析。首先其源码如下:
1 | public void refresh() throws BeansException, IllegalStateException { |
prepareRefresh()
- 让容器准备好刷新,设置启动时间和活动标识
- 初始化property源,验证环境中的property是否合法(即判断其可解析)
obtainFreshBeanFactory()
该方法是用于从子类中获取实际的Bean工厂对象。
- 先调用refreshBeanFactory()通知子类刷新Bean工厂
- 在GenericApplicationContext#refreshBeanFactory()中用了一个CAS操作将容器的refreshed属性置为true
- 再调用抽象方法getBeanFactory()获取Bean工厂,这个抽象方法就是留给子类实现的工厂方法
因此这里就是一个工厂模式的实例
prepareBeanFactory()
该方法是在获取到了容器中的Bean工厂后,配置其中的一些工具与属性。
- 设置类加载器
- 设置Bean表达式解析器,bean初始化完成后填充属性时会用到
- 添加一个PropertyEditorRegistrar,属性编辑器注册器,用于将属性编辑器(PropertyEditor)注册到容器中
- 添加一个BeanPostProcessor (ApplicationContextAwareProcessor),其功能是为各种实现了Aware接口的bean注入其需要的容器中的信息
- 设置各种Aware实现类为忽略自动装配
- 设置自动装配的类及自动装配的对象
- 根据需要添加动态织入的功能
- 注册各种默认的环境bean(Environment, SystemProperty, SystemEnvironment)
postProcessBeanFactory()
该方法在框架中是一个空方法,是预留给子类去实现的,用于在Bean工厂准备好后的一些处理工作。
invokeBeanFactoryPostProcessors()
该方法是刷新过程中最核心的一个方法,调用了容器中的BeanFactoryPostProcessor(即Bean工厂后置处理器),这是Spring框架向外暴露的一个扩展点,开发者可以通过实现该接口来对Bean工厂进行一些增强。这个方法的流程简单来说是这样:
- 先找到容器中所有的BeanDefinitionRegistryPostProcessor接口(它是BeanFactoryPostProcessor的子接口)的实现类,按顺序调用其postProcessBeanDefinitionRegistry()方法
- 再调用这些BeanDefinitionRegistryPostProcessor的postProcessBeanFacory()方法
- 最后再调用普通的BeanFactoryPostProcessor的postProcessBeanFactory()方法
具体的流程还需要单独再进行分析。
在默认情况下,此时容器中只有一个ConfigurationClassPostProcessor,它实现了BeanDefinitionRegistryPostProcessor接口。顾名思义该类的功能是在Bean工厂准备好后,处理容器中处理配置类。它的两个主要功能如下:
- postProcessBeanDefinitionRegistry()方法:找到所有的配置类,并解析这些配置类(这里所说的配置类是广义上的配置类,只要有相关的配置注解的类都会被解析)。主要处理了以下的注解:
- @PropertySource
- @ComponentScan:扫描了该注解指定的包,并将包内所有@Component注解的类都生成BeanDefinition并注册到容器中
- @Import: 根据Import注解传入的类不同(ImportSelector, ImportBeanDefinitionRegistar, 其他)有不同的处理流程,处理结束后该注解引入的类的BeanDefinition应该已经注册到容器中了
- @ImportResource
- 配置类中的@Bean方法
- 接口中的默认方法
- 如果配置类有父类,还要处理其父类
- postProcessBeanFactory()方法:对于有@Configuration注解的配置类的BeanDefinition,会将他们替换为CGLib增强的子类。
这里要为什么要做CGLib代理?看了一些源码可知道,最根本的原因是为了增强配置类中的@Bean方法,使得即使多次调用这些方法也能够得到同一个Bean对象,实现Bean的单例模式。
ConfigurationClassPostProcessor是Spring框架中最重要的一个后置处理器,实现以上功能的原理以及具体的流程也需要单独分析。
registerBeanPostProcessor()
会将所有实现了BeanPostProcessor接口的Bean注册到容器中
initMessageSource()
在容器中初始化消息源
initApplicationEventMulticaster()
初始化事件广播器
onRefresh()
空方法,也是为子类预留的,令子类能够通过重写该方法来初始化一些特殊的Bean。
registerListeners()
将实现了ApplicationListener接口的Bean注册到容器中作为监听器
finishBeanFactoryInitialization()
完成Bean工厂的初始化,生成所有单例Bean。即实例化Bean就是主要在该方法中进行的。
finishRefresh():
完成容器的刷新过程
- 初始化容器的生命周期处理器并通知其容器正在刷新
- 发布容器刷新完成的事件