Springboot 启动分析
1 @SpringBootApplication- 2 public class Application {
- 3 public static void main(String[] args) {
- 4 SpringApplication.run(Application.class, args);
- 5 }
- 6 }


- public ConfigurableApplicationContext run(String... args) {
- // 任务执行计时监听器
- StopWatch stopWatch = new StopWatch();
- stopWatch.start();
- ConfigurableApplicationContext context = null;
- Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
- // 设置系统java.awt.headless属性,确定是否开启headless模式(默认开启headless模式)
- configureHeadlessProperty();
- // SpringApplication run方法的监听器,通过 SpringFactoriesLoader 加载
- SpringApplicationRunListeners listeners = getRunListeners(args);
- // 启动监听器
- listeners.starting();
- try {
- // 创建 SpringBoot 默认启动参数
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
- // 用于设置活动和默认配置文件以及操作基础属性源的工具,即配置启动环境
- ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
- // 配置对不存在的BeanInfo类的重复 ClassLoader 访问
- configureIgnoreBeanInfo(environment);
- // 打印LOGO
- Banner printedBanner = printBanner(environment);
- // 创建合适的 ApplicationContext
- context = createApplicationContext();
- // SpringBoot 启动错误的回调接口,通过 SpringFactoriesLoader 加载
- exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
- new Class[] { ConfigurableApplicationContext.class }, context);
- // 准备 Spring 上下文
- // 在这个方法中,主要完成了以下几件事:
- // 1、设置SpringBoot的环境配置(Environment)
- // 2、注册Spring Bean名称的序列化器BeanNameGenerator,并设置资源加载器ResourceLoader
- // 3、加载ApplicationContextInitializer初始化器,并进行初始化
- // 4、统一将上面的Environment、BeanNameGenerator、ResourceLoader使用默认的Bean注册器进行注册
- prepareContext(context, environment, listeners, applicationArguments, printedBanner);
- // 注册销毁上下文的钩子
- // 刷新 Spring 上下文
- refreshContext(context);
- // 刷新后处理
- afterRefresh(context, applicationArguments);
- // 停止计时监听器
- stopWatch.stop();
- if (this.logStartupInfo) {
- // 打印计时器日志
- new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
- }
- // 上下文已刷新且应用程序已启动
- listeners.started(context);
- // 运行 ApplicationRunner 和 CommandLineRunner 的实现类
- // 二者区别在于入参不同
- callRunners(context, applicationArguments);
- }
- catch (Throwable ex) {
- handleRunFailure(context, ex, exceptionReporters, listeners);
- throw new IllegalStateException(ex);
- }
- try {
- // 发布事件以指示应用程序已准备好上下文环境为请求提供服务
- listeners.running(context);
- }
- catch (Throwable ex) {
- handleRunFailure(context, ex, exceptionReporters, null);
- throw new IllegalStateException(ex);
- }
- return context;
- }
- @Override
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
- // 准备此上下文以进行刷新。
- prepareRefresh();
- // 解析所有 Spring 配置文件,
- // 将所有 Spring 配置文件中的 bean 定义封装成 BeanDefinition,
- // 加载到 BeanFactory 中
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
- // 配置 beanFactory 的标准上下文特征,
- // 例如上下文的 ClassLoader、后置处理器等
- prepareBeanFactory(beanFactory);
- try {
- // 允许在上下文子类中对 BeanFactory 进行后续处理,
- // 默认实现为空,留给子类实现。
- postProcessBeanFactory(beanFactory);
- // 实例化和调用所有 BeanFactoryPostProcessor
- // BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,
- // Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。
- invokeBeanFactoryPostProcessors(beanFactory);
- // 注册拦截 BeanPostProcessor,
- // 将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中。
- // BeanFactoryPostProcessor 是针对 BeanFactory 的扩展,
- // 主要用在 bean 实例化之前,读取 bean 的定义,并可以修改它。
- registerBeanPostProcessors(beanFactory);
- // 初始化此上下文的消息源。
- initMessageSource();
- // 为此上下文初始化应用的事件广播器 ApplicationEventMulticaster
- initApplicationEventMulticaster();
- // 初始化特定上下文子类中的其他特殊bean ,默认实现为空。
- onRefresh();
- // 检查监听器bean并注册它们。
- registerListeners();
- // 实例化所有剩余的(非懒加载)单例。
- finishBeanFactoryInitialization(beanFactory);
- // 最后一步:发布相应的事件。
- // 完成此上下文的刷新,主要是推送上下文刷新完毕事件(ContextRefreshedEvent )到监听器。
- finishRefresh();
- }
- catch (BeansException ex) {
- if (logger.isWarnEnabled()) {
- logger.warn("Exception encountered during context initialization - " +
- "cancelling refresh attempt: " + ex);
- }
- // 销毁已创建的单例以避免闲置资源(清理不被引用的 Bean)。
- destroyBeans();
- // 重置“active”标志。
- cancelRefresh(ex);
- // 将异常传播到调用方。
- throw ex;
- }
- finally {
- // 重置Spring核心中的常见内省缓存,因为我们
- // 可能不再需要单例bean的元数据了。。。
- resetCommonCaches();
- }
- }
- }
- protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
- return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
- }
- public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
- Assert.notNull(factoryType, "'factoryType' must not be null");
- ClassLoader classLoaderToUse = classLoader;
- if (classLoaderToUse == null) {
- classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
- }
- // 加载配置文件 META-INF/spring.factories,获取自动配置的类路径,即加载 Resource 资源
- List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
- if (logger.isTraceEnabled()) {
- logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
- }
- List<T> result = new ArrayList<>(factoryImplementationNames.size());
- for (String factoryImplementationName : factoryImplementationNames) {
- // 通过反射初始化 Bean factory
- result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
- }
- AnnotationAwareOrderComparator.sort(result);
- return result;
- }


Springboot 启动分析的更多相关文章
- SpringBoot无废话入门02:SpringBoot启动分析
1.核心注解 在上文中,我们讲到了@SpringBootApplication是SpringBoot的核心注解. 可以很方便的在idea中下载源码来查看该注解的源码,如下: 可以看到,该注解本身又被其 ...
- SpringBoot启动原理分析
用了差不多两年的SpringBoot了,可以说对SpringBoot已经很熟了,但是仔细一想SpringBoot的启动流程,还是让自己有点懵逼,不得不说是自己工作和学习的失误,所以以此文对Spring ...
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(六):IoC容器依赖注入
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(一):SpringApplication类初始化过程
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(二):SpringApplication的run方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(三):SpringApplication的run方法之prepareContext()方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(四):IoC容器的初始化过程
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- 深度好文,springboot启动原理详细分析
我们开发任何一个Spring Boot项目,都会用到如下的启动类 1 @SpringBootApplication 2 public class Application { 3 public stat ...
随机推荐
- 【大咖直播】Elastic 企业搜索实战工作坊(第一期)
借助 App Search 提供的内置功能,您可轻松打造卓越的搜索体验.直观的相关度调整以及开箱即用的搜索分析,不仅可以优化所提供的内容,其提供的 API 还可帮助您将位于各处的所有内容源关联在一起. ...
- Java面向对象编程(二)
关键字 -- this 一.this关键字的使用: 1.this可以用来修饰.调用:属性.方法.构造器. 2.this修饰属性和方法: this理解为:当前对象 或 当前正在创建的对象. 2.1 在类 ...
- NOIP模拟74
前言 我就想说一句,T3 给了一个什么牛马大样例!!!!!!!!,气\(^{TM}\)死我!!!!!!! 我的 \(\mathcal{O}(n)\) 算法始终过不掉大样例我 TM ,要不然我就直接上矩 ...
- 痞子衡嵌入式:i.MXRT全系列下FlexSPI外设AHB Master ID定义与AHB RX Buffer指定的异同
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT全系列下FlexSPI外设AHB Master ID定义与AHB RX Buffer指定的异同. 因为 i.MXRT 全系列 ...
- javascriptRemke之原型的重要性
前言:JavaScript的原型对象一直是新人学习js的一大重大阻碍,但是原型的知识往往又是面试中常常会被深挖的一个点,为什么会这样呢?本文带你揭秘JavaScript原型的重要性,了解重要性之后再进 ...
- 2020.10.16--vj个人赛补题
D - Drinks Choosing Old timers of Summer Informatics School can remember previous camps in which eac ...
- Golang通脉之流程控制
流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,流程控制可以说是一门语言的"经脉". Go语言中最常用的流程控制有if和for,而switch和goto主要是为了简化代码. ...
- 3.3 Execution Flow of a DDD Based Application 基于DDD的应用程序执行流程
3.3 Execution Flow of a DDD Based Application 基于DDD的应用程序执行流程 The figure below shows a typical reques ...
- 手把手教你学Dapr - 1. .Net开发者的大时代
Dapr全称 Distributed Application Runtime,分布式应用运行时 Dapr的口号 简化云原生应用开发,聚焦在应用的核心逻辑,让代码简单.可移植 Dapr的目标 最佳实践的 ...
- Beta阶段第八次会议
Beta阶段第八次会议 时间:2020.5.24 完成工作 姓名 工作 难度 完成度 ltx 1.修改一下小程序游客模式的风格 轻 80% xyq 1.针对昨天提出的意见对场地申请表格进行修改 中 9 ...