Spring启动流程解析

一、启动Spring通常只需要一到两行代码如:

1、ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("abc.xml");

SpringBoot常用类似如下方式:

2、ConfigurableApplicationContext context = new AnnotationConfigServletWebServerApplicationContext();
context.refresh();

总体分为两大步:a.new出ApplicationContext对象。b.调用refresh()方法。其中第1类的调用refresh()方法位于构造器的最后一行代码,所以其实两类方式差不多。

refresh()方法内部大约分为12个步骤,每个步骤一个方法,其中需要重点把握的两个步骤是:

invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactory后置处理器(BFPP)

和finishBeanFactoryInitialization(beanFactory);创建普通的Bean对象,我们写的bean大部分就在这里创建。

SpringBoot的许多功能都是通过执行BeanFactory后置处理器来实现的,如自动装配。

二、梳理一下context对象的属性,其中最重要的是:

applicationContext中有属性beanFactory,beanFactory中有属性beanDefinitionMapsingletonObjects(找不到的话去父类里找)

Spring启动的核心思想逻辑,都是在为了做成1件事,总体分为两个步骤:

  1. 把项目中的类读取、解析成beanDefinition(把你我写的bean类,以spring的方式都记录下来)。
  2. 根据这些beanDefinition,生成bean对象并放入单例池singletonObjects中保存。

三、以SpringBoot为例,看看它的启动流程:

使用代码SpringApplication.run(AppStarter.class, args);来启动SpringBoot,其内部是执行SpringApplication类的run方法。根据开篇所说,先找到整体中最为重要的2个节点:

  1. new出applicationContext:context = createApplicationContext();
  2. 执行refresh方法:refreshContext(context);

在第1步之前,主要是干两件事:

  1. 加载监听器(需要熟悉观察者模式才能看懂监听器的工作原理,但是不懂也没关系,直接跳过)
  2. 加载环境environment,这个对象主要保存了我们的配置数据如application.yaml配置文件。

第1步,会顺序执行父类构造器,其中有对context部分属性进行new和赋值。

在第1和第2步中间,是给context对象的属性设置一些值,包括把environment对象设置给context等,注意这里是在refresh执行之前,这里设置的一些值后续refresh方法中能用到。

接下来开始执行refresh方法,把握最重要的两个步骤:

  1. 执行BeanFactory后置处理器。
  2. 创建普通的单例Bean。

​​​​​​​

执行BF后置处理器之前,主要是准备工作,在后面执行BF后置的时候,我们会发现context有的属性莫名奇妙的已经有值了,比如beanFactory对象,那么他们的值很可能就是在这里产生的,但是SpringBoot的话是在context构造器中new出的beanFactory,这些逻辑根据context的类型不同而异,有些xml类的context在这里解析了xml并生成beanDefinition存入beanDefinitionMap中。

执行BF后置处理器。这个地方BFPP的执行顺序有些复杂,总体来说是先执行预置,后执行自定义,并要按照order来排序执行。预置后置处理器已经保存在context中了,优先执行,其来源是之前的SpringApplication构造器或者SpringBoot的准备工作或者context的构造器,也可以是refresh前期的准备工作。BF后置处理器最重要的工作是解析整个项目的注解,生成beanDefinition放入map,或向BF中放入一些具有特定功能的bean等。对SpringBoot来讲,许多注解诸如Configuration、Import、Component、Bean等注解都是在这里被扫描并解析,生成对应的beanDefinition,注意这些beanDefinition不仅限于普通的bean,也有一些是BF后置处理器类型或者Bean后置处理器类型。新解析出来的BF后置处理器随后也将生成bean并执行。例如项目开启了AOP功能EnableAspectJAutoProxy,则就是在此处被扫描解析,生成一个Bean后置处理器的beanDefinition放到map中,后续创建普通bean的时候就能正常生成代理对象。

其他工作。如向beanFactory中放一些bean后置处理器BPP、国际化相关处理、初始化多播器(发布事件,监听器相关)、注册监听器等。SpringBoot的tomcat是在这里的onRefresh方法中创建(初始化)的。

创建普通单例bean。由于前面BFPP的执行,beanDefinitionMap中已经放满了项目中每个bean类对应的beanDefinition,此时遍历这个beanDefinitionMap,把其中的非懒加载单例bean全都创建出来并放入单例池,方式是执行getBean(beanName)方法,这个getBean方法的执行流程也就是常说的bean的生命周期的主要部分,要注意的是这里并不是首次执行getBean方法的地方,首次执行是在执行BF后置处理器时,创建了项目中自定义的BF后置处理器bean。如果生成的bean需要时代理对象,则一般是在genBean方法末期执行BeanPostProcessor们时创建代理并换掉原对象,这些BPP通常就是之前执行BFPP被放入beanDefinitionMap中的,然后就getBean出来备用。要知道,除了一些预置的,一般的BFPP和BPP包括监听器等也都是bean,只不过多实现了特定的接口而已,所以会被Spring提前创建并在各自特定的位置上使用。

最后的结束工作,SpringBoot的tomcat是在这里启动的,端口在此正式监听。

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坏猫警长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值