【Spring Boot 源码学习】Banner 信息打印流程

Spring Boot 源码学习系列

在这里插入图片描述

Banner 信息打印流程

  • 引言
  • 往期内容
  • 主要内容
    • 1. printBanner 方法
    • 2. 关闭 Banner 信息打印
    • 3. SpringApplicationBannerPrinter 类
      • 3.1 LOG 模式打印
        • 3.1.1 getBanner 方法
          • 3.1.1.1 新建 Banners
          • 3.1.1.2 添加 ImageBanner
          • 3.1.1.3 添加 ResourceBanner
          • 3.1.1.4 确认并返回 Banner 实现
        • 3.1.2 以日志模式打印
      • 3.2 CONSOLE 模式打印
        • 3.2.1 getBanner 方法
        • 3.2.2 以控制台模式打印
  • 总结

引言

上篇博文,Huazie 带大家初步了解了 SpringApplication 的实例化过程。在介绍 SpringApplication 的核心构造函数的第一个参数 ResourceLoader 时,简单提及了它用于 Spring Boot 在启动时打印对应的 Banner 信息。这里就引申出了本篇将要介绍的 Banner 信息打印流程。

在这里插入图片描述

往期内容

在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:

Spring Boot 源码学习
Spring Boot 项目介绍
Spring Boot 核心运行原理介绍
【Spring Boot 源码学习】@EnableAutoConfiguration 注解
【Spring Boot 源码学习】@SpringBootApplication 注解
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector
【Spring Boot 源码学习】自动装配流程源码解析(上)
【Spring Boot 源码学习】自动装配流程源码解析(下)
【Spring Boot 源码学习】深入 FilteringSpringBootCondition
【Spring Boot 源码学习】OnClassCondition 详解
【Spring Boot 源码学习】OnBeanCondition 详解
【Spring Boot 源码学习】OnWebApplicationCondition 详解
【Spring Boot 源码学习】@Conditional 条件注解
【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解
【Spring Boot 源码学习】RedisAutoConfiguration 详解
【Spring Boot 源码学习】JedisConnectionConfiguration 详解
【Spring Boot 源码学习】初识 SpringApplication

主要内容

1. printBanner 方法

话不多说,我们先来看 SpringApplication 中,有关打印 banner 信息的源码:

在这里插入图片描述

上述代码其实是 SpringApplication 实例化之后,在其 public ConfigurableApplicationContext run(String... args) 方法中被调用的,以下为源码截图,暂不展开介绍,下面重点介绍 printBanner 方法的执行流程。

在这里插入图片描述

2. 关闭 Banner 信息打印

我们进入 printBanner 方法,先看到了如下判断:

if (this.bannerMode == Banner.Mode.OFF) {
	return null;
}

如果 bannerMode 是关闭模式,则直接返回 null,即不打印 banner 信息。

那我们如何设置 bannerMode 为关闭模式呢?

SpringApplication 中,提供了如下的 setXXX 方法进行设置:

public void setBannerMode(Banner.Mode bannerMode) {
	this.bannerMode = bannerMode;
}

那么我们就可以在启动入口类中,这样来编写:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(DemoApplication.class);
        springApplication.setBannerMode(Banner.Mode.OFF);
        springApplication.run(args);
    }
}

将上述 setBannerMode 调用注释掉,运行 DemoApplication 类,可见如下截图:

在这里插入图片描述
setBannerMode 调用注释放开,继续运行 DemoApplication 类,可见如下截图:

在这里插入图片描述

3. SpringApplicationBannerPrinter 类

我们继续往下看源码:

ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader : new DefaultResourceLoader(null);
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);

第一行代码是获取资源加载类 ResourceLoader ,如果 SpringApplication 中的 resourceLoader 变量不为 null,则使用该变量对应的类作为资源加载类,否则新建一个 DefaultResourceLoader 作为默认的资源加载类;

第二行代码是实例化 Banner 打印类 SpringApplicationBannerPrinter ,它的构造函数分别是:

  • ResourceLoader resourceLoader : 资源加载类
  • Banner fallbackBannerbanner 信息打印接口类在这里插入图片描述

最后根据 bannerMode 的值不同,有下面两种 banner 信息打印模式:

3.1 LOG 模式打印

LOG 模式打印,可见如下:

bannerPrinter.print(environment, this.mainApplicationClass, logger);

继续查看 SpringApplicationBannerPrinter 类的 print 方法,如下图所示:

在这里插入图片描述

3.1.1 getBanner 方法

首先,这里先调用了 getBanner 方法,它用于获取一个 Banner 接口,该接口对应实际要打印的 Banner 信息的实现类。

我们查看其相关源码,如下图所示:

在这里插入图片描述

3.1.1.1 新建 Banners

BannersSpringApplicationBannerPrinter 的私有静态内部类,它实现了 Banner 接口,可以添加多个不同的 Banner 实现,也就是它组合了多个不同的 Banner 实现,其 printBanner 方法就是将内部的不同的 Banner 实现按添加顺序依次调用它们自己的 printBanner 方法进行打印。

Banners 的相关源码,如下图所示:

在这里插入图片描述

新建了 Banners 的对象 banners 之后, 我们继续往下看:

3.1.1.2 添加 ImageBanner
banners.addIfNotNull(getImageBanner(environment));

这里往 banners 中添加了一个 ImageBanner ,该类也是 Banner 接口的一个实现,用于打印从图像资源生成的 ASCII艺术【它是一种使用标准 ASCII 字符集创建的视觉艺术形式】。当然如果 getImageBanner 方法返回 null,那么 bannersaddIfNotNull 也不会处理。

我们继续看 getImageBanner 方法,如下图所示:

在这里插入图片描述

下面我们来仔细分析一下上述逻辑:

  • 首先,这里从环境配置中获取BANNER_IMAGE_LOCATION_PROPERTY 属性值【即 spring.banner.image.location 属性对应的值】;
  • 接着,判断上述 Banner 图像位置属性是否存在???
  • 如果 Banner 图像位置属性存在,则通过资源加载类 resourceLoader 获取对应路径的资源对象 resource
    • 如果资源存在,则直接返回一个 ImageBanner 的实例对象,构造参数传入上述获取的资源对象 resource
    • 如果资源不存在,则直接返回 null
  • 如果 Banner 图像位置属性不存在,则依次通过资源加载类 resourceLoader 获取 banner.gifbanner.jpgbanner.png 的图像资源 resource,如果先匹配到其中一个,则直接返回一个 ImageBanner 的实例对象,构造参数传入上述获取的图像资源 resource
  • 最后,上述都没有资源存在,则返回 null
3.1.1.3 添加 ResourceBanner
banners.addIfNotNull(getTextBanner(environment));

这里往 banners 中添加了一个 ResourceBanner,该类同样也是 Banner 接口的一个实现,用于从源文本资源中打印 Banner 信息。当然如果 getTextBanner 方法返回 null,那么 bannersaddIfNotNull 也不会处理。

我们继续看 getTextBanner 方法,如下图所示:

在这里插入图片描述

相比 getImageBanner 方法,getTextBanner 方法的逻辑就比较简单:

  • 首先,这里依旧是从环境配置中获取 BANNER_LOCATION_PROPERTY 属性对应的资源位置值【即 spring.banner.location 属性对应的值】;如果未获取到,则默认的资源位置就是 DEFAULT_BANNER_LOCATION【即 banner.txt】;
  • 接着,通过资源加载类 resourceLoader 获取指定的位置资源对象 resource
  • 然后,检查资源 resource 是否存在且其URL不包含"liquibase-core"字符串?
    • 如果满足条件,则创建一个 ResourceBanner 对象并返回。
    • 如果在尝试访问资源时发生 IOException 异常,将在 catch 语句块中忽略该异常。
  • 最后,如果没有找到符合条件的资源或发生异常,最终将返回 null
3.1.1.4 确认并返回 Banner 实现
if (banners.hasAtLeastOneBanner()) {
	return banners;
}
if (this.fallbackBanner != null) {
	return this.fallbackBanner;
}
return DEFAULT_BANNER;

如果上述的 banners 中至少存在一个 Banner 实现,则直接返回 banners 对象。

反之,如果实例化 SpringApplicationBannerPrinter 时,构造函数传入的 fallbackBanner 不为空,则直接返回 fallbackBanner 作为 最终的 Banner 实现。

如果上述都不符合要求,则返回默认的 Banner 实现 DEFAULT_BANNER 【即 SpringBootBanner】。

private static final Banner DEFAULT_BANNER = new SpringBootBanner();

SpringBootBanner 其实就是我们启动 Spring Boot 打印出来的信息,如下所示:

在这里插入图片描述

3.1.2 以日志模式打印
try {
	logger.info(createStringFromBanner(banner, environment, sourceClass));
}
catch (UnsupportedEncodingException ex) {
	logger.warn("Failed to create String for banner", ex);
}

上述 3.1.1 中的截图就是利用日志对象,打印 INFO 级别的 Banner 信息,最终会被输出到日志文件中。

Banner 的具体信息,可见 createStringFromBanner 方法,我们继续进入查看:

在这里插入图片描述

这里逻辑并不复杂,总结如下:

  • 首先,创建一个字节数组输出流 baos,用于接收要打印的 Banner 信息;
  • 接着,调用 3.1.1.4 中获取的 Banner 实现的 printBanner 方法,将要打印的 Banner 信息输出到 baos 中【这里具体看不同的 Banner 实现】;
  • 然后,从环境配置中获取 Banner 字符集属性值【即 spring.banner.charset 属性对应的值】;如果无法获取,则默认是 UTF-8
  • 最后,将字节数组输出流转换为指定字符集的字符串,并返回

3.2 CONSOLE 模式打印

默认情况下就是 CONSOLE 模式打印,可见如下:

bannerPrinter.print(environment, this.mainApplicationClass, System.out)

继续查看 SpringApplicationBannerPrinter 类的 另一个 print 方法,如下图所示:

在这里插入图片描述

3.2.1 getBanner 方法

详见 3.1.1 ,这里不再赘述。

3.2.2 以控制台模式打印

由于上面是将 System.out 传入到 PrintStream 中,所以最终是将 Banner 信息直接输出到控制台,可见如下截图:

在这里插入图片描述

总结

本篇 Huazie 带大家通读了 Banner 信息打印的源码,相信如果上面的内容都看下来的话,完全熟悉 Banner 信息打印流程不再是个问题。有了这些基础的知识,我们就可以来自定义 Banner 信息打印,敬请期待下篇博文!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/164053.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

宏--offsetof使用

文章目录 宏介绍结构体测试代码运行结果 宏介绍 宏--offsetof(type, member),type就是结构的类型,member就是需要的成员名。表达式的结果是一个size_t的值,表示这个指定成员开始存储的位置距离结构开始存储的位置偏移几个字节结构体 typede…

Django自动生成docs接口文档

1.创建Django项目 python manage.py startproject django20252.创建子应用 python manage.py startapp api3.安装依赖包 pip install coreapi4.创建urls.py from django.contrib import admin from django.urls import path, include from rest_framework import routers f…

网络运维与网络安全 学习笔记2023.11.19

网络运维与网络安全 学习笔记 第二十天 今日目标 STP工作原理、STP高级配置、MSTP工作原理 MSTP配置案例、MSTP负载均衡 STP工作原理 单点故障 PC之间的互通链路仅仅存在1个 任何一个设备或链路出现问题,PC之间都会无法通信 解决方案 增加冗余/备份设备 增加冗…

PCL 计算一条射线与一个三角形的交点

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里我们使用点向式分别表示一个射线与一个三角形,如下图所示: 其中,平面的法向量 N N N可以由三角形两条边的叉乘来计算,点R0到平面的法向距离

数学建模值TOPSIS法及代码

TOPSIS法 TOPSIS法简称为优劣距离解法,是一种常见法综合评价方法,其能充分利用原始数据的信息,其结果能精确地反映各个评价方案之间的差距。 模型介绍 上篇文章谈到的层次分析法是有局限性的。比如评价的决策层不能太多,太多的…

脚本(JavaScript)-练手-简单的随机音乐播放器

浅浅的写个简单的随机音乐播放脚本(可移动),注释很详细,直接上源码 效果: // UserScript // name 播放音乐脚本 // namespace 代码对我眨眼睛 // version 1.2 // description 在API上请求音乐链接并随机自动连续播放音乐&…

【MySQL--->事务】

文章目录 [TOC](文章目录) 一、基本概念二、事务的操作1.设置全局事务隔离级别2.设置事务提交方式3.事务操作 三、事务隔离性1.隔离性概念2 .隔离级别设置 四、MVCC多版本控制2. read view 一、基本概念 事务是由若干条具有逻辑相关性的SQL语句组成的,用来完成某种任务的**逻辑…

使用 C 语言快速排序将字符串按照 ASCII 码升序排列

示例代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h>static Comp(const void *a, const void *b) {char *pa (char *)a;char *pb (char *)b;return strcmp(a, b); }int main(void) {char strs[3][10] { "bd", &q…

SpringBoot 整合 JdbcTemplate

数据持久化有几个常见的方案&#xff0c;有 Spring 自带的 JdbcTemplate 、有 MyBatis&#xff0c;还有 JPA&#xff0c;在这些方案中&#xff0c;最简单的就是 Spring 自带的 JdbcTemplate 了&#xff0c;这个东西虽然没有 MyBatis 那么方便&#xff0c;但是比起最开始的 Jdbc…

关于爬虫中的hook(defineProperty,hook cookies, hook载荷数据,hookXHR)

关于爬虫中的hook&#xff1a; defineProperty var people {age: 19, }; var count20; console.log(people.age) // 参数&#xff1a;对象 属性名字 函数 Object.defineProperty(people, age, {get: function () {console.log(获取值&#xff01;);return count;},// set: …

C++ map和set的使用

关联式容器 vector、list、deque统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;存储的是元素本身 侧重于单纯的存储数据 关联式容器也是用来存储数据的&#xff0c;里面存储的是<key, value>结构的键值对&#xff0c;在数据检索时比序列式…

漫谈广告机制设计 | 万剑归宗:聊聊广告机制设计与收入提升的秘密(2)

书接上文漫谈广告机制设计 | 万剑归宗&#xff1a;聊聊广告机制设计与收入提升的秘密&#xff08;1&#xff09;&#xff0c;我们谈到流量作为一种有限资源&#xff0c;其分配方式&#xff08;或者交易方式&#xff09;也经历了几个阶段&#xff1a;第一个是谈判定价阶段&#…

新材料工厂生产管理mes系统

万界星空科技新材料云MES系统从需求分析、产品选型、系统集成、可扩展性和灵活性以及安全性和稳定性等多个角度进行考虑。 如果您的企业也属于新材料生产制造行业&#xff0c;同时也计划通过MES系统来进行整个生产过程的数字化管控。 欢迎搜索万界星空科技线上咨询或者直接拨…

论文阅读:JINA EMBEDDINGS: A Novel Set of High-Performance Sentence Embedding Models

Abstract JINA EMBEDINGS构成了一组高性能的句子嵌入模型&#xff0c;擅长将文本输入转换为数字表示&#xff0c;捕捉文本的语义。这些模型在密集检索和语义文本相似性等应用中表现出色。文章详细介绍了JINA EMBEDINGS的开发&#xff0c;从创建高质量的成对&#xff08;pairwi…

搭建网关服务器实现DHCP自动分配、HTTP服务和免密登录

目录 一. 实验要求 二. 实验准备 三. 实验过程 1. 网关服务器新建网卡并改为仅主机模式 2. 修改新建网卡IP配置文件并重启服务 3. 搭建网关服务器的dhcp服务 4. 修改server2网卡配置文件重启服务并效验 5. 设置主机1的网络连接为仅主机模式 6. 给server2和网关服务器之…

YOLOv4 学习记录

文章目录 整体概况数据增强Mosaic数据增强 基于CSPNet网络思想的架构改进Mish激活函数CSPNetCSPNet 3 大优势Partial Transition 层 CSPDarkNet (yolo v4 中的CSPDarkNet53) NeckSPPNetPAN-FPN 结构 正负样本匹配损失函数IOU 损失函数IOU的2个问题&#xff1a; GIOU Loss示意图…

力扣hot100 两数之和 哈希表

&#x1f468;‍&#x1f3eb; 力扣 两数之和 &#x1f60b; 思路 在一个数组中如何快速找到某一个数的互补数&#xff1a;哈希表 O(1)实现⭐ AC code class Solution {public int[] twoSum(int[] nums, int target){HashMap<Integer, Integer> map new HashMap<&g…

STM32CubeMX学习笔记(2)--DSP库的使用

1.DSP库简介 STM32的DSP库是为了支持数字信号处理应用而设计的&#xff0c;它包含了一系列优化的数学函数和算法&#xff0c;能够在STM32微控制器上高效地执行数字信号处理任务。 DSP库通常包括以下主要特性&#xff1a; 1.数学函数库&#xff1a; 包括各种基本的数学运算函数…

STM32电源名词解析

先来简单了解一下各种电源端口的命名 VCC&#xff1a;Ccircuit 表示电路的意思, 即接入电路的电压 VDD&#xff1a;Ddevice 表示器件的意思, 即器件内部的工作电压。 VSS&#xff1a;Sseries 表示公共连接的意思&#xff0c;通常指电路公共接地端电压。 GND&#xff1a;在电…

设计模式——责任链模式

文章目录 责任链模式的定义场景示例责任链模式实现方案责任链模式扩展责任链模式的优缺点责任链模式在框架源码中的应用 责任链模式的定义 责任链模式又称职责链模式&#xff0c;是一种行为型设计模式。官方描述&#xff1a;使多个对象都有机会处理请求&#xff0c;从而避免请…