SpringBoot中是如何打印banner的呢?我们如何自定义banner?
SpringApplication的printBanner方法如下所示,其是一个桥梁。进行了必要的判断后,获取resourceLoader 和bannerPrinter,然后将任务交给了bannerPrinter去处理。
Banner printedBanner = printBanner(environment); private Banner printBanner(ConfigurableEnvironment environment) { // 默认是CONSOLE 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); if (this.bannerMode == Mode.LOG) { return bannerPrinter.print(environment, this.mainApplicationClass, logger); } // 交给banner打印器去处理 return bannerPrinter.print(environment, this.mainApplicationClass, System.out); }
使用banner打印器SpringApplicationBannerPrinter打印banner信息。
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) { //获取到banner 可能是banners哦 Banner banner = getBanner(environment); // 触发其printBanner方法 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; } if (this.fallbackBanner != null) { return this.fallbackBanner; } // 返回默认banner return DEFAULT_BANNER; }
搜索图片banner
如下所示,如果配置了路径则从路径下面获取;否则从系统资源路径(classpath)下尝试获取banner.jpg、banner.png、banner.gif。
private Banner getImageBanner(Environment environment) { // spring.banner.image.location 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; }
搜索文本banner
如果spring.banner.location
存在则尝试获取其下资源,否则l尝试获取banner.txt
。
//String BANNER_LOCATION_PROPERTY = "spring.banner.location"; //String DEFAULT_BANNER_LOCATION = "banner.txt"; 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
也就是DEFAULT_BANNER,其就是一个SpringBootBanner实例。
private static final Banner DEFAULT_BANNER = new SpringBootBanner();
如下所示,是不是很熟悉?
② 打印banner
banner.printBanner(environment, sourceClass, out);
如果你拿到的banner是一个banners,也就是Banner.banners实例。如下所示,会获取内部维护的banners列表循环触发每个实例的printBanner方法。
@Override public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) { for (Banner banner : this.banners) { banner.printBanner(environment, sourceClass, out); } }
Banner有如下实现,本文这里是默认的SpringBootBanner 。
SpringBootBanner (org.springframework.boot) PrintedBanner in SpringApplicationBannerPrinter (org.springframework.boot) Banners in SpringApplicationBannerPrinter (org.springframework.boot) ResourceBanner (org.springframework.boot) ImageBanner (org.springframework.boot)
会打印出如下效果:
③ 自定义banner
如何自定义banner呢,看了流程之后就会发现很简单,你自定义一个banner.txt扔到classpath即可。