SpringBoot启动logo配置

起始每次打开Spring Boot的应用的main方法时,都会出现下面如下所示Spring的Logo。之前没有注意过这个Logo的配置,直到看到一个Spring Cloud的开源示例项目时,看到了一个配置如下:有一个问题:为什么放在classpath下且名字为banner.txt就能够配置成功?源码

起始

每次打开Spring Boot的应用的main方法时,都会出现下面如下所示Spring的Logo。

启动logo

之前没有注意过这个Logo的配置,直到看到一个Spring Cloud的开源示例项目时,看到了一个配置如下:

logo配置

有一个问题:为什么放在classpath下且名字为banner.txt就能够配置成功?

源码中的配置

入口

public static void main(String[] args) {
    SpringApplication.run(CustomerStarter.class, args);
}

最终执行的逻辑为:public ConfigurableApplicationContext run(String... args)这个方法, 如下所示:

printBanner入口

首先是设置不同的打印Logo的模式,模式包括日志、标准输出、关闭三种。

设置不同的Logo打印方式

获取banner的步骤来了

public Banner print(Environment environment, Class<?> sourceClass, Log logger) {
    Banner banner = getBanner(environment);
    try {
        logger.info(createStringFromBanner(banner, environment, sourceClass));
    }
    catch (UnsupportedEncodingException ex) {
        logger.warn("Failed to create String for banner", ex);
    }
    return new PrintedBanner(banner, sourceClass);
}

实际的获取都是在getBanner()这个方法里面,如下:

private Banner getBanner(Environment environment) {
    Banners banners = new Banners();
    banners.addIfNotNull(getImageBanner(environment));
    banners.addIfNotNull(getTextBanner(environment));
    if (banners.hasAtLeastOneBanner()) {
        return banners;
    }
    if (this.fallbackBanner != null) {
        return this.fallbackBanner;
    }
    return DEFAULT_BANNER;
}

由上可知,存在两种banner,一种是文字类型的,一种是图片类型的。这两个banner都会被加载到banners中。获取文字和图片banner的源码如下:

// 文字Logo
private Banner getImageBanner(Environment environment) {
    String location = environment.getProperty(BANNER_IMAGE_LOCATION_PROPERTY);
    if (StringUtils.hasLength(location)) {
        Resource resource = this.resourceLoader.getResource(location);
        return resource.exists() ? new ImageBanner(resource) : null;
    }
    for (String ext : IMAGE_EXTENSION) {
        Resource resource = this.resourceLoader.getResource("banner." + ext);
        if (resource.exists()) {
            return new ImageBanner(resource);
        }
    }
    return null;
}
// 图片Logo
private Banner getTextBanner(Environment environment) {
    String location = environment.getProperty(BANNER_LOCATION_PROPERTY,
            DEFAULT_BANNER_LOCATION);
    Resource resource = this.resourceLoader.getResource(location);
    if (resource.exists()) {
        return new ResourceBanner(resource);
    }
    return null;
}

其中environment.getProperty()有两个参数,第一个是配置在yaml中的路径,第二个就是默认值,分别为:

static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";
static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";
static final String DEFAULT_BANNER_LOCATION = "banner.txt";

至此,分析完毕。

这里还有一个问题,如何进行配置不同的打印方式?
// bannerMode的设置方法
public void setBannerMode(Banner.Mode bannerMode) {
    this.bannerMode = bannerMode;
}
// 调用setBannerMode的方法
public SpringApplicationBuilder bannerMode(Banner.Mode bannerMode) {
    this.application.setBannerMode(bannerMode);
    return this;
}
// 因此需要通过构建者模式来构建出一个SpringApplication,然后通过这个实例来运行run方法
// 构建的步骤可以参考如下代码
public static void main(String[] args) {
    SpringApplicationBuilder builder = new SpringApplicationBuilder(CustomerStarter.class);
    builder.bannerMode(Banner.Mode.OFF);
    builder.build(args).run(args);
}

配置效果如下图所示:

配置logo模式之后的效果

Read more

Volcano 与 Kubernetes GPU 调度学习笔记

本笔记系统整理 Volcano 调度器、Kubernetes 调度框架、GPU Device Plugin、HAMi 等云原生 AI 调度领域的核心知识,适合用于学习、复习和工程实践参考。 目录 * 第一部分:Volcano 入门 * 1. Volcano 是什么 * 2. 安装与快速使用 * 3. 核心特性一览 * 第二部分:Volcano 整体架构 * 4. Volcano 解决的核心问题 * 5. 整体架构与数据流 * 6. 三层抽象模型 * 第三部分:Volcano 核心实现原理 * 7. Session 机制 * 8. Gang Scheduling 实现 * 9. Queue 与 DRF 公平调度

容器镜像(4):镜像的常用工具箱

容器镜像(4):镜像的常用工具箱

前几篇在讲多架构镜像时已经用过 skopeo 和 crane 做镜像复制,这篇系统整理这两个工具的完整能力,同时介绍几个日常操作镜像时同样好用的工具。 一、skopeo:不依赖 Daemon 的镜像瑞士军刀 skopeo 的核心价值是绕过 Docker daemon,直接与 Registry API 交互。上一篇用它做镜像复制和离线传输,但它的能力远不止于此。 1.1 安装 # Ubuntu / Debian sudo apt install -y skopeo skopeo --version # skopeo version 1.15.1 1.2 inspect:免拉取检查镜像元数据 docker inspect 需要先把镜像拉到本地,skopeo inspect 直接向 Registry

容器镜像(3):多架构镜像构建

容器镜像(3):多架构镜像构建

一、什么是多架构镜像 1.1 OCI Image Index 上一篇介绍了单平台镜像的结构:一个 Manifest 指向 Config 和若干 Layer blob。多架构镜像在此之上多了一层——OCI Image Index(也叫 Manifest List),是一个轻量的索引文件,把多个单平台 Manifest 组织在一起: $ docker manifest inspect golang:1.22-alpine { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests&

容器镜像(2):containerd 视角下的镜像

容器镜像(2):containerd 视角下的镜像

一、为什么需要了解 containerd 如果你只用 docker run 跑容器,从来不关心底层,那可以不了解 containerd。但如果你在用 Kubernetes,或者想真正理解"容器运行时"是什么,containerd 是绕不开的。 事实上,当你执行 docker run 的时候,containerd 早就在后台悄悄工作了——Docker 从 1.11 版本开始,就把核心运行时剥离出来交给 containerd 负责。 1.1 Docker 的架构演变 早期的 Docker(1.10 及之前)是一个"大一统"的单体程序:一个 dockerd