前言
我們肯定很好奇,當我們啓動 springboot 的時候,這個下面的 banner 是怎麼打印出來的呢?
以及我們可不可以定製我們自己的banner,那我們就進入一下 SpringBoot 的源碼,看下他是怎麼加載的吧
PS:文章同步更新於Github–Java-Notes,如果某些圖片看不了可以直接從這個上面觀看
源碼分析
項目結構
入口
private Banner printBanner(ConfigurableEnvironment environment) {
// 判斷是否關閉了 banner 打印模式
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
// 初始化資源加載器
ResourceLoader resourceLoader = (this.resourceLoader != null)
? this.resourceLoader : new DefaultResourceLoader(getClassLoader());
// 初始化 banner 打印對象
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(
resourceLoader, this.banner);
// 如果在 log中打印 banner
if (this.bannerMode == Mode.LOG) {
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
// 如果在 控制檯打印banner
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
// 只有三種模式,關閉 控制檯 和log文件中
enum Mode {
/**
* Disable printing of the banner.
*/
OFF,
/**
* Print the banner to System.out.
*/
CONSOLE,
/**
* Print the banner to the log file.
*/
LOG
}
public Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
// 獲取banner,看了這個我們就知道怎麼去更改 banner了
Banner banner = getBanner(environment);
// 打印 banner
banner.printBanner(environment, sourceClass, out);
return new PrintedBanner(banner, sourceClass);
}
private Banner getBanner(Environment environment) {
// 創建一個局部對象 Banners ,這個對象繼承自 Banner接口,內容很簡單,保存banner信息,添加banner方法,打印banner方法
Banners banners = new Banners();
// 添加banner ,這個裏面還有些道道
banners.addIfNotNull(getImageBanner(environment));
banners.addIfNotNull(getTextBanner(environment));
if (banners.hasAtLeastOneBanner()) {
return banners;
}
if (this.fallbackBanner != null) {
return this.fallbackBanner;
}
// 如果都沒有,那麼就會打印默認的 banner, 我們都見過
return DEFAULT_BANNER;
}
// 獲取 圖像banner 信息
private Banner getImageBanner(Environment environment) {
// 獲取配置文件中的 banner 位置信息
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;
}
// 如果配置文件中沒有指明,我們就讀取默認的配置,banner前綴開頭的,挨個遍歷匹配。按照 gif。jpg、png的順序,所以如果匹配到前面的圖片,後面的就不會顯示
for (String ext : IMAGE_EXTENSION) {
Resource resource = this.resourceLoader.getResource("banner." + ext);
if (resource.exists()) {
return new ImageBanner(resource);
}
}
return null;
}
// 默認的 banner
class SpringBootBanner implements Banner {
private static final String[] BANNER = { "",
" . ____ _ __ _ _",
" /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\",
"( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
" \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )",
" ' |____| .__|_| |_|_| |_\\__, | / / / /",
" =========|_|==============|___/=/_/_/_/" };
private static final String SPRING_BOOT = " :: Spring Boot :: ";
private static final int STRAP_LINE_SIZE = 42;
@Override
public void printBanner(Environment environment, Class<?> sourceClass,
PrintStream printStream) {
for (String line : BANNER) {
printStream.println(line);
}
String version = SpringBootVersion.getVersion();
version = (version != null) ? " (v" + version + ")" : "";
StringBuilder padding = new StringBuilder();
while (padding.length() < STRAP_LINE_SIZE
- (version.length() + SPRING_BOOT.length())) {
padding.append(" ");
}
printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT,
AnsiColor.DEFAULT, padding.toString(), AnsiStyle.FAINT, version));
printStream.println();
}
}
實驗
我們準備了 四個文件,gif、jpg、png、txt。打印出來是這樣的,上面是 gif的內容,下面是 txt的內容
我們在配置文件中指定文件,就不會按照默認的來進行顯示了