大家好,欢迎来到IT知识分享网。
Spring容器是怎么初始化的
原创声明
本人署名原创文章,未经许可不支持转载。本公众号所有文章均原创,为了容易理解和记忆,文章以图解为主、代码为辅。如果您感兴趣,欢迎关注!
文/吴潇(Java Senior)
本文分析Spring容器初始化过程。在Spring Framework中,所有类型的容器都是由ApplicationContext接口表示的,而AbstractApplicationContext是这个接口的第一个实现,包含适用于各类容器的公共代码。所以我们分析容器初始化过程,主要是分析AbstractApplicationContext中跟初始化相关的代码。
![Spring容器是怎么初始化的插图1 Spring容器是怎么初始化的](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
类结构
如果从Web应用中常用的XmlWebApplicationContext容器开始,不断查找父类,可以得知Spring容器的主体代码在AbstractApplicationContext这个类中。Spring容器类的继承关系如下图所示。
![Spring容器是怎么初始化的插图3 Spring容器是怎么初始化的](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
AbstractApplicationContext的父类DefaultResourceLoader只负责加载资源,AbstractApplicationContext在内部维护一个BeanFactory(负责管理bean definition,今后将单独撰文分析),并且管理由这个BeanFactory创建的bean,并且AbstractApplicationContext还负责检测在BeanFactory中定义的特殊bean,从而实现容器自身功能以及支持扩展。
顺便讲一个用Idea快速看UML类图的技巧
Spring除提供多种类型的容器,还为Bean定义提供xml、注解、Java等多种配置方式,涉及类比较多,我们可能对ApplicationContext、BeanFactory等的关系感到困惑,其实可用一张图概括如下。
![Spring容器是怎么初始化的插图5 Spring容器是怎么初始化的](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
上图看不清没关系,用Intellij IDEA打开任何一个使用到Spring的项目,找到XmlWebApplicationContext类,把光标移到类名上,使用以下功能即可立即生成UML。
![Spring容器是怎么初始化的插图7 Spring容器是怎么初始化的](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
特殊作用的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容器是怎么初始化的插图9 Spring容器是怎么初始化的](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/56574.html