Spring有两种方式加载配置,分别为xml文件、注解的方式,对于xml配置的方式相信大家都不陌生,往往通过new ClassPathXmlApplicationContext("*.xml")就能启动容器了,下面让我们来看看Spring的容器启动都做了哪些事情。

1、ClassPatchXmlApplicationContext的类图结构

从类图我们可以得到的信息:
  1,ClassPatchXmlApplicationContext是一个容器 ,是BeanFactory的子类;
  2,ClassPatchXmlApplicationContext是一个资源加载器,是ResourceLoader的子类。

2、ClassPatchXmlApplicationContext构造器

 1 public ClassPathXmlApplicationContext(
2 String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
3 throws BeansException {
4 // 调用父类构造方法
5 super(parent);
6 // 资源路径设置到当前上下文中
7 setConfigLocations(configLocations);
8 // 刷新容器
9 if (refresh) {
10 refresh();
11 }
12 }

2.1、调用父类构造器

  最终会调用到父类AbstractApplicationContext的构造方法。
  1、初始化AbstractApplicationContext的资源路径解析器resourcePatternResolver 属性;
  2、为当前上下文设置父上下文环境,若父上下文环境不为空,将父上下文环境合并到当前上下文环境中。
 1 // 构造器
2 public AbstractApplicationContext(@Nullable ApplicationContext parent) {
3 this();
4 setParent(parent);
5 }
6 // 初始化资源路径解析器
7 public AbstractApplicationContext() {
8 // 创建资源模式处理器
9 this.resourcePatternResolver = getResourcePatternResolver();
10 }
11 // 设置父容器
12 public void setParent(@Nullable ApplicationContext parent) {
13 this.parent = parent;
14 // 若父容器不为空,则将父容器的环境配置合并到当前容器中
15 if (parent != null) {
16 Environment parentEnvironment = parent.getEnvironment();
17 if (parentEnvironment instanceof ConfigurableEnvironment) {
18 getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
19 }
20 }
21 }

2.2、设置资源路径

  对父类AbstractRefreshableConfigApplicationContext的configLocations做赋值,将配置资源配置文件位置设置到当前应用程序上下文中。
 1 // 设置资源路径
2 public void setConfigLocations(@Nullable String... locations) {
3 if (locations != null) {
4 Assert.noNullElements(locations, "Config locations must not be null");
5 this.configLocations = new String[locations.length];
6 for (int i = 0; i < locations.length; i++) {
7 this.configLocations[i] = resolvePath(locations[i]).trim();
8 }
9 }
10 else {
11 this.configLocations = null;
12 }
13 }

2.3、刷新容器 - Spring的IOC容器的核心启动流程

 1 // 刷新容器的流程
2 @Override
3 public void refresh() throws BeansException, IllegalStateException {
4 synchronized (this.startupShutdownMonitor) {
5 // 容器刷新前的准备工作
6 prepareRefresh();
7 // 创建容器对象DefaultListableBeanFactory,加载xml配置文件的属性值到当前工厂中
8 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
9 // beanFactory的准备工作,对各种属性进行填充
10 prepareBeanFactory(beanFactory);
11
12 try {
13 // 子类覆盖方法做额外的处理,web中的代码有具体实现
14 postProcessBeanFactory(beanFactory);
15
16 // 调用各种beanFactory处理器
17 invokeBeanFactoryPostProcessors(beanFactory);
18
19 // 注册bean处理器,这里只是注册功能,真正调用的地方在getBean方法
20 registerBeanPostProcessors(beanFactory);
21
22 // 为上下文初始化message源,即不同语言的消息体,国际化处理,在springmvc的有实际应用
23 initMessageSource();
24
25 // 初始化事件监听多路广播器
26 initApplicationEventMulticaster();
27
28 // 留给子类来初始化其他的bean
29 onRefresh();
30
31 // 在所有注册的bean中查找listener bean,注册到消息广播器中
32 registerListeners();
33
34 // 初始化剩下的单实例(非懒加载的)
35 finishBeanFactoryInitialization(beanFactory);
36
37 // 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知
38 finishRefresh();
39 }
40
41 catch (BeansException ex) {
42 if (logger.isWarnEnabled()) {
43 logger.warn("Exception encountered during context initialization - " +
44 "cancelling refresh attempt: " + ex);
45 }
46
47 // 为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean
48 destroyBeans();
49
50 // 重置active标志
51 cancelRefresh(ex);
52
53 throw ex;
54 }
55 finally {
56 // 重置缓存
57 resetCommonCaches();
58 }
59 }
60 }

综上可见,Spring容器启动的核心方法,这些方法后序会做详细介绍

1、prepareRefresh()

  刷新容器前的准备工作

2、obtainFreshBeanFactory()

  创建容器,并加载配置并生成BeanDefinition,加载至缓存。为后续创建bean对象做准备工作。

3、prepareBeanFactory(beanFactory)

  beanFactory的准备工作,主要是用来为容器填充属性

4、postProcessBeanFactory(beanFactory)

  beanFactory容器的后置处理器

5、invokeBeanFactoryPostProcessors(beanFactory)

  调用各种BeanFactoryPostProcessors的后置处理器,实例化BeanFactoryPostProcessor类型的bean对象,包括ConfigurationClassPosyProcessor类对注解的处理,也是SpringBoot自动配置的基础。

6、registerBeanPostProcessors(beanFactory)

  调用各种BeanPostProcessor的后置处理器,实例化BeanPostProcessor类型的bean对象,包括对Spring AOP的自动代理创建器AspectJAwareAdvisorAutoProxyCreator的实例的创建。

7、finishBeanFactoryInitialization(beanFactory)

  初始化定义的bean实例。

8、finishRefresh()

  完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程

最新文章

  1. Java|今天起,别再扯订阅和回调函数
  2. 每日一问:面试结束时面试官问&quot;你有什么问题需要问我呢&quot;,该如何回答?
  3. occ添加新的捕捉模式
  4. 性能测试知多少---系统架构分析 转自https://yq.aliyun.com/articles/35147?spm=5176.100239.blogcont24251.8.lS96At
  5. 安卓--selector简单使用
  6. codeforces 300E Empire Strikes Back 数论+二分查找
  7. C# 动态语言特性,dynamic 关键字研究
  8. asp.net mvc 注册中的邮箱激活功能实现(一)
  9. 【FAQ系列】:DB服务器产生大量物理读问题优化思路
  10. 单张滑动tab 组件
  11. PS 滤镜——素描算法(一)
  12. mysql数据表增删改查
  13. ES6的let
  14. 机器学习环境搭建-Pycharm
  15. 机器学习基石笔记:03 Types of Learning
  16. tomcat cluster配置实战注意事项
  17. 八、面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)
  18. CentOS 6.7下配置 yum 安装 Nginx。
  19. Codeforces Round #275 (Div. 2) 题解
  20. Android之扫描二维码和根据输入信息生成名片二维码

热门文章

  1. Elasticsearch:同步 MongoDB 数据到 Elasticsearch
  2. NodeJS 服务 Docker 镜像极致优化指北
  3. 安装 LAMP 环境(yum 版本) shell脚本
  4. Java注解(2):实现自己的ORM
  5. Linux执行jsp命令的时候报错:-bash: jps: command not found
  6. Sentinel 介绍与下载使用
  7. 文本挖掘与NLP笔记——代码向:分词
  8. Log4shell漏洞研究及其挖矿案例分析
  9. Pictionary 方法记录
  10. xss学习笔记(萌新版)