Spring容器是怎么初始化的

Spring容器是怎么初始化的

原创声明

本人署名原创文章,未经许可不支持转载。本公众号所有文章均原创,为了容易理解和记忆,文章以图解为主、代码为辅。如果您感兴趣,欢迎关注!

文/吴潇(Java Senior)

本文分析Spring容器初始化过程。在Spring Framework中,所有类型的容器都是由ApplicationContext接口表示的,而AbstractApplicationContext是这个接口的第一个实现,包含适用于各类容器的公共代码。所以我们分析容器初始化过程,主要是分析AbstractApplicationContext中跟初始化相关的代码。

Spring容器是怎么初始化的

类结构

如果从Web应用中常用的XmlWebApplicationContext容器开始,不断查找父类,可以得知Spring容器的主体代码在AbstractApplicationContext这个类中。Spring容器类的继承关系如下图所示。

Spring容器是怎么初始化的

AbstractApplicationContext的父类DefaultResourceLoader只负责加载资源,AbstractApplicationContext在内部维护一个BeanFactory(负责管理bean definition,今后将单独撰文分析),并且管理由这个BeanFactory创建的bean,并且AbstractApplicationContext还负责检测在BeanFactory中定义的特殊bean,从而实现容器自身功能以及支持扩展。

顺便讲一个用Idea快速看UML类图的技巧

Spring除提供多种类型的容器,还为Bean定义提供xml、注解、Java等多种配置方式,涉及类比较多,我们可能对ApplicationContext、BeanFactory等的关系感到困惑,其实可用一张图概括如下。

Spring容器是怎么初始化的

上图看不清没关系,用Intellij IDEA打开任何一个使用到Spring的项目,找到XmlWebApplicationContext类,把光标移到类名上,使用以下功能即可立即生成UML。

Spring容器是怎么初始化的

特殊作用的Bean

接着前面,我们说到AbstractApplicationContext内部包含一个BeanFactory,它负责为容器创建bean;而AbstractApplicationContext负责检测BeanFactory中定义的bean是不是特殊bean,并且使用这些特殊bean完成相关的功能。例如,类型为MessageSource的bean负责为Spring翻译文本(名称必须为messageSource),类型为ApplicationEventMulticaster的bean负责为Spring容器发送事件(名称必须定义为applicationEventMulticaster)。

比较常用的特殊bean包括BeanFactoryPostProcessor和BeanPostProcessor,其中,BeanFactoryPostProcessor负责对容器整体进行一些修改或功能扩展,而BeanPostProcessor则负责对每一个普通的bean进行一个修改或扩展。用户只要把实现了这两个接口的bean部署在容器中,就可以对Spring容器进行扩展了。

初始化过程(refresh)

AbstractApplicationContext的初始化过程就体现在refresh方法中。

1)首先,把容器定义中的占位符变量(以$符号开头的属性变量)替换为真正的值(AbstractApplicationContext只定义了一个算法框架,具体实现在子类中),然后检查必须解析的占位符变量替换成功没有,如果有$变量未解析,则抛出MissingRequiredPropertiesException,停止初始化。

2)然后,刷新内部的bean factory(即调用refreshBeanFactory),并且返回刷新后的bean factory。这一步操作所做的主要工作,用通俗的语言来描述就是,让bean factory重新加载bean definition配置。

3)得到bean factory之后,对这个bean factory进行一系列配置,例如设置bean class loader等,把bean factory所依赖的组件传给bean factory,例如BeanExpressionResolver和PropertyEditorRegistrar。同时,在bean factory标记一些特殊的类,让他们不参与到autowiring,注册一些特殊的singleton对象到bean factory。

4)在bean definition加载完成后(实例化所有bean之前),配置BeanPostProcessors,把它们注册到bean factory中。

5)调用BeanFactoryPostProcessor,对容器进行一些处理。

6)实例化并调用BeanPostProcessor。

7)创建MessageSource。

8)创建ApplicationEventMulticaster。

9)创建其他特殊bean。

10)注册事件监听器。

11)实例化所有非lazy-init的singleton bean。

12)清理掉容器中的资源缓存等。

13)创建LifecycleProcessor类型的特殊bean,再去调用这个bean的onRefresh方法,去执行其他与refresh相关的工作。

14)在容器中发布ContextRefreshedEvent事件,代表容器已刷新(初始化)完成。

以上就是AbstractApplicationContext中refresh的执行动作。

以上我们分析了Spring容器的初始化过程,希望对您的工作和面试都有帮助。如果对互联网编程技术、Java、Spring、Android、C/C++、Linux、个性化推荐、Community Detection、Machine Learning、Deep Learning、Data Mining、Gnuplot、LaTeX等技术感兴趣的话,欢迎关注本公众号(不限于Java)。

Spring容器是怎么初始化的