我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java SpringBoot核心源码的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java SpringBoot核心源码的示例分析

本篇文章给大家分享的是有关Java SpringBoot核心源码的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

    SpringBoot源码主线分析

    我们要分析一个框架的源码不可能通过一篇文章就搞定的,本文我们就来分析下SpringBoot源码中的主线流程。先掌握SpringBoot项目启动的核心操作,然后我们再深入每一个具体的实现细节,注:本系列源码都以SpringBoot2.2.5.RELEASE版本来讲解

    1.SpringBoot启动的入口

    当我们启动一个SpringBoot项目的时候,入口程序就是main方法,而在main方法中就执行了一个run方法。

    @SpringBootApplicationpublic class StartApp {public static void main(String[] args) {SpringApplication.run(StartApp.class);}}

    2.run方法

    然后我们进入run()方法中看。代码比较简单

    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {// 调用重载的run方法,将传递的Class对象封装为了一个数组return run(new Class<?>[] { primarySource }, args);}

    调用了重载的一个run()方法,将我们传递进来的类对象封装为了一个数组,仅此而已。我们再进入run()方法。

    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {// 创建了一个SpringApplication对象,并调用其run方法// 1.先看下构造方法中的逻辑// 2.然后再看run方法的逻辑return new SpringApplication(primarySources).run(args);}

    在该方法中创建了一个SpringApplication对象。同时调用了SpringApplication对象的run方法。这里的逻辑有分支,先看下SpringApplication的构造方法中的逻辑

    3.SpringApplication构造器

    我们进入SpringApplication的构造方法,看的核心代码为

    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {// 传递的resourceLoader为nullthis.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");// 记录主方法的配置类名称this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 记录当前项目的类型this.webApplicationType = WebApplicationType.deduceFromClasspath();// 加载配置在spring.factories文件中的ApplicationContextInitializer对应的类型并实例化// 并将加载的数据存储在了 initializers 成员变量中。setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 初始化监听器 并将加载的监听器实例对象存储在了listeners成员变量中setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 反推main方法所在的Class对象 并记录在了mainApplicationClass对象中this.mainApplicationClass = deduceMainApplicationClass();}

    在本方法中完成了几个核心操作

    推断当前项目的类型

    加载配置在spring.factories文件中的ApplicationContextInitializer中的类型并实例化后存储在了initializers中。

    和2的步骤差不多,完成监听器的初始化操作,并将实例化的监听器对象存储在了listeners成员变量中

    通过StackTrace反推main方法所在的Class对象

    上面的核心操作具体的实现细节我们在后面的详细文章会给大家剖析

    4.run方法

    接下来我们在回到SpringApplication.run()方法中。

    public ConfigurableApplicationContext run(String... args) {// 创建一个任务执行观察器StopWatch stopWatch = new StopWatch();// 开始执行记录执行时间stopWatch.start();// 声明 ConfigurableApplicationContext 对象ConfigurableApplicationContext context = null;// 声明集合容器用来存储 SpringBootExceptionReporter 启动错误的回调接口Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();// 设置了一个名为java.awt.headless的系统属性// 其实是想设置该应用程序,即使没有检测到显示器,也允许其启动.//对于服务器来说,是不需要显示器的,所以要这样设置.configureHeadlessProperty();// 获取 SpringApplicationRunListener 加载的是 EventPublishingRunListener// 获取启动时到监听器SpringApplicationRunListeners listeners = getRunListeners(args);// 触发启动事件listeners.starting();try {// 构造一个应用程序的参数持有类ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 创建并配置环境ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 配置需要忽略的BeanInfo信息configureIgnoreBeanInfo(environment);// 输出的Banner信息Banner printedBanner = printBanner(environment);// 创建应用上下文对象context = createApplicationContext();// 加载配置的启动异常处理器exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);// 刷新前操作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);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);}// 返回上下文对象--> Spring容器对象return context;}

    在这个方法中完成了SpringBoot项目启动的很多核心的操作,我们来总结下上面的步骤

    • 创建了一个任务执行的观察器,统计启动的时间

    • 声明ConfigurableApplicationContext对象

    • 声明集合容器来存储SpringBootExceptionReporter即启动错误的回调接口

    • 设置java.awt.headless的系统属性

    • 获取我们之间初始化的监听器(EventPublishingRunListener),并触发starting事件

    • 创建ApplicationArguments这是一个应用程序的参数持有类

    • 创建ConfigurableEnvironment这时一个配置环境的对象

    • 配置需要忽略的BeanInfo信息

    • 配置Banner信息对象

    • 创建对象的上下文对象

    • 加载配置的启动异常的回调异常处理器

    • 刷新应用上下文,本质就是完成Spring容器的初始化操作

    • 启动结束记录启动耗时

    • 完成对应的事件广播

    • 返回应用上下文对象。

    以上就是Java SpringBoot核心源码的示例分析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网行业资讯频道。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Java SpringBoot核心源码的示例分析

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Java SpringBoot核心源码的示例分析

    本篇文章给大家分享的是有关Java SpringBoot核心源码的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。SpringBoot源码主线分析我们要分析一个框架的源码
    2023-06-22

    Druid核心源码分析DruidDataSource

    这篇“Druid核心源码分析DruidDataSource”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Druid核心源码分
    2023-07-05

    Java源码ConcurrentHashMap的示例分析

    小编给大家分享一下Java源码ConcurrentHashMap的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、记录形式打算直接把过程写在源码中,会按序进行注释,查阅的时候可以按序号只看注释部分二、Concur
    2023-06-15

    Spring AOP核心功能源码分析

    这篇“Spring AOP核心功能源码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring AOP核心功能源码分析
    2023-07-05

    Java中Handler源码的示例分析

    这篇文章主要介绍了Java中Handler源码的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。从很早开始就认识到 Handler 了,只不过那时修为尚浅,了解的不够深
    2023-06-02

    java中CopyOnWriteArrayList源码的示例分析

    这篇文章将为大家详细讲解有关java中CopyOnWriteArrayList源码的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。简介CopyOnWriteArrayList是ArrayList的
    2023-06-29

    kafka核心消费逻辑源码分析

    本篇内容主要讲解“kafka核心消费逻辑源码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“kafka核心消费逻辑源码分析”吧!消费逻辑框架搭建好之后着手开发下kafka的核心消费逻辑,流式图
    2023-07-06

    Java源码解析之ConcurrentHashMap的示例分析

    小编给大家分享一下Java源码解析之ConcurrentHashMap的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!早期 ConcurrentHashMap,其实现是基于:分离锁,也就是将内部进行分段(Segme
    2023-06-15

    关于PHP核心功能的示例分析

    关于PHP核心功能的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。PHP是我们一直都很关注的语言之一,随着PHP6的升级,它的功能也越来越强大,我们这里
    2023-06-17

    源码分析Vue3响应式核心之effect

    这篇文章主要为大家详细介绍了Vue3响应式核心之effect的相关知识,文中的示例代码讲解详细,对我们学习Vue3有一定的帮助,需要的可以参考一下
    2023-05-17

    源码分析Vue3响应式核心之reactive

    这篇文章主要为大家详细介绍了Vue3响应式核心之reactive的相关知识,文中的示例代码讲解详细,对我们学习Vue3有一定的帮助,需要的可以参考一下
    2023-05-17

    laravel的核心实例分析

    本文小编为大家详细介绍“laravel的核心实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“laravel的核心实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。laravel的核心是服务容器,也就是
    2023-06-29

    PHP底层内核源码之变量的示例分析

    小编给大家分享一下PHP底层内核源码之变量的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!PHP变量的四个基本特征:1.变量命名变量命名上,PHP继承了P
    2023-06-15

    Java notify唤醒源代码的示例分析

    这期内容当中小编将会给大家带来有关Java notify唤醒源代码的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java notify唤醒在此对象监视器上等待的单个线程。相关的问题需要我们不断的
    2023-06-17

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录