亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot打印Banner的實現示例

 更新時間:2025年01月08日 09:48:19   作者:冬天vs不冷  
本文主要介紹了SpringBoot啟動Banner的實現原理和打印流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

在前文中,我們深入解析了SpringBoot啟動時應用環(huán)境的準備過程。接下來將深入介紹啟動Banner打印的具體實現及流程。

SpringBoot版本2.7.18SpringApplication的run方法的執(zhí)行邏輯如下,本文將詳細介紹第5小節(jié):打印啟動Banner

// SpringApplication類方法
public ConfigurableApplicationContext run(String... args) {
    // 記錄應用啟動的開始時間
    long startTime = System.nanoTime();

    // 1.創(chuàng)建引導上下文,用于管理應用啟動時的依賴和資源
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;

    // 配置無頭模式屬性,以支持在無圖形環(huán)境下運行
    // 將系統(tǒng)屬性 java.awt.headless 設置為 true
    configureHeadlessProperty();

    // 2.獲取Spring應用啟動監(jiān)聽器,用于在應用啟動的各個階段執(zhí)行自定義邏輯
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 啟動開始方法(發(fā)布開始事件、通知應用監(jiān)聽器ApplicationListener)
    listeners.starting(bootstrapContext, this.mainApplicationClass);

    try {
        // 3.解析應用參數
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

        // 4.準備應用環(huán)境,包括讀取配置文件和設置環(huán)境變量
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);

        // 配置是否忽略 BeanInfo,以加快啟動速度
        configureIgnoreBeanInfo(environment);

        // 5.打印啟動Banner
        Banner printedBanner = printBanner(environment);

        // 6.創(chuàng)建應用程序上下文
        context = createApplicationContext();
        
        // 設置應用啟動的上下文,用于監(jiān)控和管理啟動過程
        context.setApplicationStartup(this.applicationStartup);

        // 7.準備應用上下文,包括加載配置、添加 Bean 等
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

        // 8.刷新上下文,完成 Bean 的加載和依賴注入
        refreshContext(context);

        // 9.刷新后的一些操作,如事件發(fā)布等
        afterRefresh(context, applicationArguments);

        // 計算啟動應用程序的時間,并記錄日志
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
        }

        // 10.通知監(jiān)聽器應用啟動完成
        listeners.started(context, timeTakenToStartup);

        // 11.調用應用程序中的 `CommandLineRunner` 或 `ApplicationRunner`,以便執(zhí)行自定義的啟動邏輯
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        // 12.處理啟動過程中發(fā)生的異常,并通知監(jiān)聽器
        handleRunFailure(context, ex, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        // 13.計算應用啟動完成至準備就緒的時間,并通知監(jiān)聽器
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
    }
    catch (Throwable ex) {
        // 處理準備就緒過程中發(fā)生的異常
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }

    // 返回已啟動并準備就緒的應用上下文
    return context;
}

一、入口

// 5.打印啟動Banner
Banner printedBanner = printBanner(environment);

// 打印啟動 Banner 的方法,根據配置的 Banner 模式選擇打印方式
private Banner printBanner(ConfigurableEnvironment environment) {
    // 如果 Banner 模式被設置為 OFF,則不打印 Banner,直接返回 null
    if (this.bannerMode == Banner.Mode.OFF) {
        return null;
    }

    // 確定資源加載器。如果當前實例的 resourceLoader 不為空,則使用它;否則創(chuàng)建一個默認的資源加載器
    ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
            : new DefaultResourceLoader(null);

    // 創(chuàng)建 Banner 打印器,負責加載和打印 Banner
    SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);

    // 根據 Banner 模式決定打印到日志還是控制臺
    if (this.bannerMode == Mode.LOG) {
        // 如果 Banner 模式為 LOG,則將 Banner 打印到日志中
        return bannerPrinter.print(environment, this.mainApplicationClass, logger);
    }

    // 默認情況下(CONSOLE 模式),將 Banner 打印到標準輸出(控制臺)
    return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

二、Banner接口類

// 一個用于以編程方式輸出 Banner 的接口類
@FunctionalInterface
public interface Banner {
	// 將 Banner 輸出到指定的打印流
	void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);

	// 用于配置 Banner 的模式枚舉
	enum Mode {
		// 禁用 Banner 的打印
		OFF,
		// 將 Banner 輸出到 System.out
		CONSOLE,
		// 將 Banner 輸出到日志文件
		LOG
	}
}

1、打印Banner開關

  • 默認情況是打印到控制臺

在這里插入圖片描述

  • 可以通過properties或yml設置關閉打印Banner
spring.main.banner-mode=off

上一節(jié)有講spring.main開頭的屬性會綁定到SpringApplication對象上,這樣就可以通過配置文件的屬性來決定Banner的打印模式。

三、打印Banner過程

1、console和log模式

  • console控制臺模式,默認設置
// SpringApplicationBannerPrinter類方法
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
    // 根據提供的環(huán)境信息獲取橫幅。
    Banner banner = getBanner(environment);
    
    // 將橫幅打印到指定的輸出流中。
    banner.printBanner(environment, sourceClass, out);
    
    // 返回一個 PrintedBanner 對象,包含打印的橫幅和源類信息。
    return new PrintedBanner(banner, sourceClass);
}
  • log日志文件模式,通過在配置文件中設置spring.main.banner-mode=log,可以將應用啟動Banner輸出到日志文件中
// SpringApplicationBannerPrinter類方法
Banner print(Environment environment, Class<?> sourceClass, Log logger) {
	// 根據提供的環(huán)境信息獲取橫幅。
	Banner banner = getBanner(environment);
	try {
		logger.info(createStringFromBanner(banner, environment, sourceClass));
	}
	catch (UnsupportedEncodingException ex) {
		logger.warn("Failed to create String for banner", ex);
	}
	// 返回一個 PrintedBanner 對象,包含打印的橫幅和源類信息。
	return new PrintedBanner(banner, sourceClass);
}
  • log模式就是獲取打印流內容轉換為字符串,然后由log日志打印罷了

在這里插入圖片描述

兩種方式都會返回一個PrintedBanner對象,主要是為以后在應用上下文中注冊為Bean或供其他組件使用做準備。

2、四種Banner對象

  • 圖片和文本橫幅組合的Banners
  • 備用Banner
  • 默認Banner
// SpringApplicationBannerPrinter類方法

// 默認Banner
private static final Banner DEFAULT_BANNER = new SpringBootBanner();

// 根據當前環(huán)境獲取適當的橫幅(Banner)
private Banner getBanner(Environment environment) {
    // 創(chuàng)建一個 Banners 對象,用于存儲圖片和文本橫幅
    Banners banners = new Banners();
    // 嘗試獲取圖片橫幅,并將其添加到 Banners 中(如果非空)
    banners.addIfNotNull(getImageBanner(environment));
    // 嘗試獲取文本橫幅,并將其添加到 Banners 中(如果非空)
    banners.addIfNotNull(getTextBanner(environment));
    // 如果至少包含一個橫幅,則返回組合的 Banners 對象
    if (banners.hasAtLeastOneBanner()) {
        return banners;
    }
    
    // 如果沒有任何橫幅但存在備用橫幅,則返回備用橫幅
    if (this.fallbackBanner != null) {
        return this.fallbackBanner;
    }
    
    // 如果沒有任何橫幅,則返回默認橫幅
    // Banner DEFAULT_BANNER = new SpringBootBanner();
    return DEFAULT_BANNER;
}
  • Banners對象內部持有多個Banner實現類,遍歷調用Banner的printBanner方法

在這里插入圖片描述

2.1、圖片Banner

  • 嘗試根據環(huán)境信息獲取圖片橫幅(Image Banner)
  • 環(huán)境變量spring.banner.image.location用于指定圖片路徑;如果未設置,則默認加載路徑為banner.gif、banner.jpgbanner.png(按順序查找)。
private Banner getImageBanner(Environment environment) {
    // 從環(huán)境變量中獲取橫幅圖片的路徑
    // String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";
    String location = environment.getProperty(BANNER_IMAGE_LOCATION_PROPERTY);
    
    // 如果路徑不為空,嘗試加載對應的資源
    if (StringUtils.hasLength(location)) {
        Resource resource = this.resourceLoader.getResource(location);
        // 如果資源存在,返回對應的 ImageBanner 對象
        return resource.exists() ? new ImageBanner(resource) : null;
    }

    // 如果未指定路徑,嘗試加載默認圖片橫幅文件
    // String[] IMAGE_EXTENSION = { "gif", "jpg", "png" };
    for (String ext : IMAGE_EXTENSION) {
        Resource resource = this.resourceLoader.getResource("banner." + ext);
        // 如果找到存在的文件資源,返回對應的 ImageBanner 對象
        if (resource.exists()) {
            return new ImageBanner(resource);
        }
    }
    // 如果沒有找到任何圖片橫幅資源,返回 null
    return null;
}

控制臺效果

在這里插入圖片描述

2.2、文字Banner

  • 嘗試根據環(huán)境信息獲取文本橫幅(Text Banner)
  • 環(huán)境變量spring.banner.location用于指定文本路徑;如果未設置,則默認加載路徑為banner.txt。
private Banner getTextBanner(Environment environment) {
    // 獲取橫幅的路徑,優(yōu)先使用環(huán)境變量中的配置,如果沒有配置則使用默認路徑
    // String BANNER_LOCATION_PROPERTY = "spring.banner.location";
    // String DEFAULT_BANNER_LOCATION = "banner.txt";
    String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);

    // 使用 ResourceLoader 加載指定路徑的資源
    Resource resource = this.resourceLoader.getResource(location);

    try {
        // 檢查資源是否存在,且路徑中不包含 "liquibase-core"(防止加載到不相關的資源)
        if (resource.exists() && !resource.getURL().toExternalForm().contains("liquibase-core")) {
            // 如果資源有效,返回對應的 ResourceBanner 對象
            return new ResourceBanner(resource);
        }
    } catch (IOException ex) {
        // 忽略異常,可能是資源加載時出錯或路徑無效
        // 在這里不拋出異常,而是返回 null,表示沒有有效的橫幅資源
    }
    // 如果資源無效或發(fā)生異常,返回 null
    return null;
}

控制臺效果

在這里插入圖片描述

2.2、備用Banner

SpringApplicationBannerPrinter對象的備用Banner屬性fallbackBanner是由SpringApplication對象的私有屬性banner傳遞而來的。

在這里插入圖片描述

  • 可以在SpringBoot啟動類中通過調用SpringApplicationsetBanner方法直接設置自定義的Banner對象
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        // 設置全局備用橫幅
        app.setBanner((environment, sourceClass, out) -> {
            out.println("===== 全局備用橫幅 =====");
            out.println(" 默認橫幅已啟用 ");
            out.println("=====================");
        });
        app.run(args);
    }
}

控制臺效果

在這里插入圖片描述

2.3、默認Banner

如果未設置自定義文字圖片Banner或備用Banner,SpringBoot將使用默認的啟動橫幅(SpringBootBanner)作為顯示內容。

// 默認的 Banner 實現,用于打印 "Spring" 的啟動橫幅,和版本信息
class SpringBootBanner implements Banner {

    // 預定義的 ASCII 藝術橫幅,每行為一個數組元素
	private static final String[] BANNER = { 
		"", 
		"  .   ____          _            __ _ _",
		" /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\",
		"( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
		" \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )", 
		"  '  |____| .__|_| |_|_| |_\\__, | / / / /",
		" =========|_|==============|___/=/_/_/_/" 
	};

	// 固定的 Spring Boot 標識符,用于橫幅輸出
	private static final String SPRING_BOOT = " :: Spring Boot :: ";

	// 橫幅固定寬度,用于計算 padding 的空格數
	private static final int STRAP_LINE_SIZE = 42;

	/**
	 * 輸出橫幅到指定的 PrintStream(如控制臺或日志)。
	 */
	@Override
	public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
		// 遍歷并打印每一行 ASCII 藝術橫幅
		for (String line : BANNER) {
			printStream.println(line);
		}
		// 獲取 Spring Boot 的版本信息
		String version = SpringBootVersion.getVersion();
		// 如果版本信息不為空,則格式化為 "(vX.X.X)"
		version = (version != null) ? " (v" + version + ")" : "";
		
		// 構造 padding 空格,使橫幅版本號對齊
		StringBuilder padding = new StringBuilder();
		while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {
			padding.append(" ");
		}

		// 打印 Spring Boot 標識符和版本信息,使用 ANSI 輸出樣式
		printStream.println(AnsiOutput.toString(
			AnsiColor.GREEN,       // 綠色輸出 Spring Boot 標識符
			SPRING_BOOT, 
			AnsiColor.DEFAULT,     // 恢復默認顏色
			padding.toString(),    // 填充的空格
			AnsiStyle.FAINT,       // 微弱樣式(淡化顯示版本信息)
			version                // 版本號
		));
		// 添加空行用于分隔橫幅和其他輸出
		printStream.println();
	}
}

控制臺效果

在這里插入圖片描述

總結

本文全面解析了SpringBoot啟動橫幅的實現原理、打印流程及自定義方法,介紹了文本橫幅(默認路徑為banner.txt,可通過spring.banner.location配置)、圖片橫幅(默認路徑為banner.gif、banner.jpgbanner.png,可通過spring.banner.image.location配置)、備用橫幅和默認橫幅的使用,幫助開發(fā)者靈活運用橫幅機制提升項目啟動體驗。

到此這篇關于SpringBoot打印Banner的實現示例的文章就介紹到這了,更多相關SpringBoot打印Banner內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳解如何在Java中加密和解密zip文件

    詳解如何在Java中加密和解密zip文件

    在本文中,我們來學習如何用Zip4j庫創(chuàng)建受密碼保護的壓縮文件并將其解壓,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以參考一下
    2022-09-09
  • 詳談Lock與synchronized 的區(qū)別

    詳談Lock與synchronized 的區(qū)別

    下面小編就為大家?guī)硪黄斦凩ock與synchronized 的區(qū)別。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 如何在mapper文件中使用in("str1","str2")

    如何在mapper文件中使用in("str1","str2")

    這篇文章主要介紹了如何在mapper文件中使用in("str1","str2"),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java基礎學習之方法的重載知識總結

    Java基礎學習之方法的重載知識總結

    今天帶大家來回顧Java基礎知識,文中對Java方法的重載相關知識作了非常詳細的介紹,對正在學習java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-05-05
  • Java搭建RabbitMq消息中間件過程詳解

    Java搭建RabbitMq消息中間件過程詳解

    這篇文章主要介紹了Java搭建RabbitMq消息中間件過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • Socket+JDBC+IO實現Java文件上傳下載器DEMO詳解

    Socket+JDBC+IO實現Java文件上傳下載器DEMO詳解

    這篇文章主要介紹了Socket+JDBC+IO實現Java文件上傳下載器DEMO詳解,需要的朋友可以參考下
    2017-05-05
  • Spring Boot整合swagger使用教程詳解

    Spring Boot整合swagger使用教程詳解

    這篇文章主要介紹了Spring Boot整合swagger使用教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Java三個類加載器及它們的相互關系

    Java三個類加載器及它們的相互關系

    Java在需要使用類別的時候,才會將類別加載,Java的類別載入是由類別載入器(Class loader)來達到的,預設上,在程序啟動之后,主要會有三個類別加載器,文中詳細介紹了這三個類加載器,需要的朋友可以參考下
    2021-06-06
  • Spring spel表達式使用方法示例

    Spring spel表達式使用方法示例

    這篇文章主要介紹了Spring spel表達式使用方法示例,通過一些實例向大家展示了spel表達式的用法,需要的朋友可以了解下。
    2017-09-09
  • @Transactional解讀(作用、失效場景與解決方式)

    @Transactional解讀(作用、失效場景與解決方式)

    這篇文章主要介紹了關于@Transactional作用、失效場景與解決方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評論