基本概念
- Spring Boot启动时显示的字符图案就是banner。
- 五种banner输出:
- 默认banner

- 文字banner
- 设置banner.txt
- 设置spring.banner.location
- 图片banner
- 设置banner.gif/png/jpg
- 设置spring.banner.image.location
- 兜底banner:在没有显式设置文字或图片时显示的banner
- springApplication.setBanner()
- 关闭banner
- 设置spring.main.banner-mode=off
源码分析
获取banner
// 在run()方法中调用
private Banner printBanner(ConfigurableEnvironment environment) {
// banner关闭
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
// 实例化资源加载器
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(getClassLoader());
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
// 打印到日志当中还是控制台
if (this.bannerMode == Mode.LOG) {
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
// 在printBanner中调用
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
// 获取banner并打印
Banner banner = getBanner(environment);
banner.printBanner(environment, sourceClass, out);
return new PrintedBanner(banner, sourceClass);
}
// 获取banner
private Banner getBanner(Environment environment) {
Banners banners = new Banners();
// 图片banner
banners.addIfNotNull(getImageBanner(environment));
// 文字banner
banners.addIfNotNull(getTextBanner(environment));
if (banners.hasAtLeastOneBanner()) {
return banners;
}
// 兜底banner
if (this.fallbackBanner != null) {
return this.fallbackBanner;
}
// 默认banner
return DEFAULT_BANNER;
}
// 获取图片banner
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;
}
// IMAGE_EXTENSION集合包括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
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;
}
输出banner
// 1. 打印默认Banner
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
// BANNER是一个定义在源码中的字符串,遍历每一行进行打印
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();
}
// 2. 打印文字banner
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
try {
// 指定字符集,获取文本内容
String banner = StreamUtils.copyToString(this.resource.getInputStream(),
environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));
for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {
// 替换占位符并输出
banner = resolver.resolvePlaceholders(banner);
}
out.println(banner);
}
catch (Exception ex) {
logger.warn(LogMessage.format("Banner not printable: %s (%s: '%s')", this.resource, ex.getClass(),
ex.getMessage()), ex);
}
}
// 3. 打印图片banner
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
// 是否在headless模式下工作
String headless = System.getProperty("java.awt.headless");
try {
System.setProperty("java.awt.headless", "true");
// 获取图片的信息(长宽边界旋转等,使用java readFrames来打印)
printBanner(environment, out);
}
catch (Throwable ex) {
logger.warn(LogMessage.format("Image banner not printable: %s (%s: '%s')", this.image, ex.getClass(),
ex.getMessage()));
logger.debug("Image banner printing failure", ex);
}
finally {
if (headless == null) {
System.clearProperty("java.awt.headless");
}
else {
System.setProperty("java.awt.headless", headless);
}
}
}