SpringBoot(二)--SpringBoot启动源码分析

入口类

在这里插入图片描述

SpringApplication实例化

进入SpringApplication.run(HelloWorldMainApplication.class, args);方法:
在这里插入图片描述
SpringApplication构造器:
在这里插入图片描述

设置应用类型

在这里插入图片描述
引入的依赖中spring-boot-starter-web的配置文件又会引入Tomcat和spring-webmvc.spring-webmvc中存在DispatcherServlet这个类,也就是SpringMVC的核心Servlet,通过类加载能加载DispatcherServlet这个类,那么应用类型自然就是WebApplicationType.SERVLET

设置初始化器(Initializer)

函数getSpringFactoriesInstances( ApplicationContextInitializer.class)
在这里插入图片描述
loadFactoryNames函数源码:
在这里插入图片描述
spring-boot-autoconfigure这个包为例,它的META-INF/spring.factories部分定义如下:
在这里插入图片描述
SharedMetadataReaderFactoryContextInitializerAutoConfigurationReportLoggingInitializer这两个类名被读取出来,然后放入到Set<String>集合(保存的是要加载的类名)中,然后开始实例化操作:
在这里插入图片描述
初始化器就是org.springframework.context.ApplicationContextInitializer的实现类,这个接口的定义为:
在这里插入图片描述
在Web应用中,注册Property Sources或者是激活Profiles。Property Sources就是配置文件;Profiles是Spring为了在不同环境下(如DEV、TEST、PRODUCTION等),加载不同的配置项而抽象出来的一个实体。

设置监听器(Listener)

在这里插入图片描述
函数getSpringFactoriesInstances的实现:
在这里插入图片描述

spring-boot-autoconfigure这个包中的spring.factories中的Key-Value为:
在这里插入图片描述
这10个监听器会贯穿SpringBoot整个生命周期。到此为止,对于SpringApplication实例的初始化过程就结束了。

调用run方法

总体处理流程

  1. 获取并启动监听器
  2. 根据SpringApplicationRunListeners以及参数来准备环境
  3. 创建Spring容器
  4. Spring容器前置处理
  5. 刷新容器
  6. Spring容器后置处理
  7. 发出结束执行的事件
  8. 执行Runners

源码分析

在这里插入图片描述
在这里插入图片描述

获取并启动监听器

获取监听器

在这里插入图片描述
META-INF/spring.factories中读取Key为org.springframework.boot.SpringApplicationRunListener的Values:
在这里插入图片描述

在函数getSpringFactoriesInstances中利用反射获取实例时会触发EventPublishingRunListener的构造函数,该函数的具体实现为:
在这里插入图片描述
添加广播器的源码:
该方法定义在SimpleApplicationEventMulticaster父类AbstractApplicationEventMulticaster中。
在这里插入图片描述
在这里插入图片描述
综上我们可以看到:EventPublishingRunListener中有一个广播器SimpleApplicationEventMulticaster,广播器SimpleApplicationEventMulticaster中又存放所有的监听器。

启动监听器

通过getRunListeners方法获取的监听器为EventPublishingRunListener该监听器是启动事件发布监听器,主要用来发布启动事件
在这里插入图片描述
首先来看一下SpringApplicationRunListener这个接口:
在这里插入图片描述SpringBoot启动时第一个启动事件listeners.starting()
在这里插入图片描述
继续看SimpleApplicationEventMulticaster的核心方法:
在这里插入图片描述
这里有四种监听器:
在这里插入图片描述
以SpringBoot的日志监听器为例,核心代码:因为该事件类型为ApplicationEvent,所以会执行onApplicationStartedEvent((ApplicationStartedEvent) event);SpringBoot会在运行过程中的不同阶段,发送各种事件,来执行对应监听器的对应方法
在这里插入图片描述

环境构建

在这里插入图片描述
具体实现:
在这里插入图片描述
在这里插入图片描述
函数listeners.environmentPrepared(environment);,这里是第二次发布事件,根据事件类型获取到的监听器为:
在这里插入图片描述
其中的ConfigFileApplicationListener非常核心,主要用来处理项目配置,项目中的propertiesyml文件都是其内部类所加载。
在这里插入图片描述
首先还是会读spring.factories文件,List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();获取的处理类有以下四种:
在这里插入图片描述
在执行完上述三个监听器流程后,ConfigFileApplicationListener会执行该类本身的逻辑,由其内部类Loader加载项目制定路径下的配置文件:
在这里插入图片描述
到此为止,项目的变量配置已全部加载完毕。
在这里插入图片描述
一共有6个配置文件,取值顺序由上到下。也就是说前面的配置变量会覆盖后面同名的配置变量

创建容器

首先需要了解一下什么是容器?

Spring容器是Spring框架的核心,是用来管理对象的,容器创建对象,把它们连接在一起,配置他们,并管理他们的整个生命周期,从创建到销毁。
在java项目中,使用了org.springframework.context.ApplicationContext接口的实现类;在web项目中,使用了spring.xml—Spring的配置文件(在xml中配置了一系列我们需要的bean,配置之后Spring就会按照我们配置的东西进行解析,从而得到我们需要的值)。
Spring提供了两种不同类型的容器:
BeanFactory容器:它是最简单的容器
ApplicationContext:该容器继承自BeanFactory,包括BeanFactory容器的所有功能。

在这里插入图片描述
具体实现:
在这里插入图片描述

Spring容器前置处理

这一步主要是在容器刷新之前的准备动作,包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
在这里插入图片描述
具体实现:
在这里插入图片描述
调用初始化器:
在这里插入图片描述
我们也可以自定义初始化器,并实现initialize方法,然后放入METAINF/spring.factories配置文件中Key为:org.springframework.context.ApplicationContextInitializer的value中,这里我们自定义的初始化器就会被调用,是项目初始化的一种方式。
加载启动指定类
在创建SpringApplication实例中,先将HelloWorldMainApplication.class存储在this.primarySources属性中,现在就是用这个属性的时候了,getAllSources()方法的具体实现:
在这里插入图片描述

函数load(context, sources.toArray(new Object[0]));的具体实现:
在这里插入图片描述
通知监听器,容器已准备就绪:
在这里插入图片描述
主要还是针对一些日志等监听器的响应处理。

刷新容器

执行到这里,springBoot相关的处理工作已经结束,接下来的工作就交给Spring了,接下来我们来看一下refreshContext(context);函数,该方法是实现IOC和AOP的关键。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Spring容器后置处理

在这里插入图片描述
扩展接口,设计模式中的模板方法,默认为空实现。如果有自定义需求,可以重写该方法,比如打印一些启动结束log,或者一些其他后置处理。

发出结束执行的事件

在这里插入图片描述
这里是在Spring容器中发布事件,并不是在SpringApplication中发布事件,和前面的starting是不同的,前面的starting是直接向SpringApplication中的11个监听器发布启动事件。

执行Runners

函数callRunners(context, applicationArguments);源码:
在这里插入图片描述
如果是CommandLineRunner的话,执行如下代码:
在这里插入图片描述
我们也可以自定义一些ApplicationRunner或者CommandLineRunner,实现其run方法,并注入到Spring容器中,在SpringBoot启动完成之后,会执行所有的runnner的run方法。

感谢并参考:
https://www.cnblogs.com/java-chen-hao/p/11829344.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值