Spring 容器启动时所执行的各项操作
Spring 容器启动时所执行的各项操作
Spring 中的 AbstractApplicationContext 是 ApplicationContext 的抽象实现类,该实现类的 refresh() 方法定义了 Spring 容器在加载配置文件后的各项处理过程,这些处理过程氢气的刻画了 Spring 容器启动时所执行的各项操作。下面来看下 refresh() 内部定义了哪些执行逻辑。
// 1.初始化 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 交给子类处理 BeanFactory
postProcessBeanFactory(beanFactory);
// 2.调用工厂后处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 3.注册 Bean 后处理器
registerBeanPostProcessors(beanFactory);
// 4. 初始化消息源
initMessageSource();
// 5.初始化应用上下文事件广播器
initApplicationEventMulticaster();
// 6. 初始化其他特殊的Bean , 由具体子类实现
onRefresh();
// 7. 注册事件监听器
registerListeners();
// 8. 初始化所有单实例的 Bean ,使用 懒加载模式的 Bean 除外
finishBeanFactoryInitialization(beanFactory);
// 9.完成刷新并发布容器刷新事件
finishRefresh();
-
初始化 BeanFactory : 根据配置文件初始化 BeanFactory ,在 obtainFreshBeanFactory() 方法中,首先调用 refreshBeanFactory() 方法刷新 BeanFactory , 然后调用 getBeanFactory() 方法获取 BeanFactory ,这两个方法具体都是由子类实现。这一步里, Spring 将配置文件的信息装入 Bean 定义注册表中 BeanDefintionRegistry 中,但此时 Bean 还未初始化。
-
调用工厂后处理器: 根据反射机制从 BeanDefintionRegistry 中找出所有实现了 BeanFactoryPostProcessor 接口的 Bean ,并调用其
postProcessBeanFactory() 方法。
-
注册 Bean 后处理器 : 根据反射机制从 BeanDefintionRegistry 中找出所有实现了 BeanPostProcessor 接口的 Bean ,并将它们注册到容器 Bean 后处理器的注册表中。
-
初始化消息源 :初始化容器的国际化消息源。
-
初始化应用上下文事件广播器。
-
初始化其他特殊的 Bean :这个一个钩子方法,子类可以借助这个方法执行一些特殊的操作,如 AbstractRefreshableApplicationContext 使用该方法执行初始化 ThemeSource 的操作。
-
注册事件监听器。
-
初始化所有单例的 Bean,使用懒加载的 Bean 除外,初始化 Bean 后,将其放入 Spring 容器的缓存池中。
-
发布上下文刷新事件:创建上下文刷新事件,事件广播器负责将这些事件广播到每个注册的事件监听器中。
在文章的上一步部分,我们看到了 Bean 从创建到销毁的生命历程,这些过程都可以从上面的流程中找到对应的步骤。Spring 协调多个组件共同完成这个复杂的作业流程。如下图描述了 Spring 容器从加载配置文件到创建处一个完整的 Bean 的作业流程及参与的角色 。
-
ResourceLoader 从存储介质中加载 Spring 配置信息 , 并使用 Resource 表示这个配置文件资源 。
-
BeanDefinitionReader 读取 Resource 所指向的配置资源,然后解析配置文件。配置文件中的每个 <bean> 解析成一个 BeanDefinition 对象,并保存到 BeanDefinitionRegistry 中。
-
容器扫描 BeanDefinitionRegistry 中的 BeanDefinition ,使用 Java 反射机制自动识别出 Bean 工厂后处理器 (实现 BeanFactoryPostProcessor 接口的 Bean),然后调用这些 Bean 工厂后处理器对 BeanDefinitionRegistry 中的 BeanDefinition 进行加工处理。主要完成以下两项工作 :
(1).对使用占位符的 <bean> 元素标签进行解析,得到最终的配置值。这意味着对一些半成品式的 BeanDefinition 对象进行加工处理并得到成品的 BeanDefinition 对象。
(2).对 BeanDefinitionRegistry 中的 BeanDefinition 进行扫描,通过 Java 反射机制找出所有属性编辑器的 Bean (实现 Java.beans.PropertyEditor 接口的 Bean),并自动将它们注册到 Spring 容器的属性编辑器注册表中(PropertyEditorRegistry)。 -
Spring 容器从 BeanDefinitionRegistry 中取出加工后的 BeanDefinition ,并调用 InstantiationStrategy 进行 Bean 实例化工作。
-
在实例化 Bean 时,Spring 容器将使用 BeanWrapper 对 Bean 进行封装。 BeanWrapper 提供了很多以 Java 反射机制操作 Bean 的方法,它将结合该 Bean 的 BeanDefinition 及容器中的属性编辑器,完成 Bean 属性注入工作。
-
利用容器中注册的 Bean 后处理器(实现 BeanPostProcessor 接口的 Bean)对已完成属性设置工作的 Bean 进行后续加工,直接装配出一个准备就绪的 Bean 。