美文网首页
手撕SpringBoot源码---启动时如何自定义Banner

手撕SpringBoot源码---启动时如何自定义Banner

作者: Felix_ | 来源:发表于2021-11-07 11:09 被阅读0次

    SpringBoot启动之后,默认会打印SpringBootBanner,想要修改它,网上有很多的文章介绍,只要在resources中添加定义的banner.txt或者banner.png等都可以,但是他是怎么样的一个加载过程呢,我们来看下SpringBoot启动之后,对于Banner的处理,常见入口函数如下

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

    在调用SpringApplicationrun方法之后

    public ConfigurableApplicationContext run(String... args) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            DefaultBootstrapContext bootstrapContext = createBootstrapContext();
            ConfigurableApplicationContext context = null;
            configureHeadlessProperty();
            SpringApplicationRunListeners listeners = getRunListeners(args);
            listeners.starting(bootstrapContext, this.mainApplicationClass);
            try {
                ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
                ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
                configureIgnoreBeanInfo(environment);
                Banner printedBanner = printBanner(environment);
                context = createApplicationContext();
                context.setApplicationStartup(this.applicationStartup);
                prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
                refreshContext(context);
                afterRefresh(context, applicationArguments);
                stopWatch.stop();
                if (this.logStartupInfo) {
                    new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
                }
                listeners.started(context);
                callRunners(context, applicationArguments);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, listeners);
                throw new IllegalStateException(ex);
            }
    
            try {
                listeners.running(context);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, null);
                throw new IllegalStateException(ex);
            }
            return context;
        }
    

    这里有个专门用于输出banner的方法printBanner(environment)

        private Banner printBanner(ConfigurableEnvironment environment) {
            if (this.bannerMode == Banner.Mode.OFF) {
                return null;
            }
            ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
                    : new DefaultResourceLoader(null);
            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);
        }
    

    在此处可以看到,如果我们没有定义resourceLoader,那么就会采用默认的DefaultResourceLoader来加载资源。同时,会创建一个SpringApplicationBannerPrinter来进行banner输出,默认的banner是什么?

        static final String DEFAULT_BANNER_LOCATION = "banner.txt";
    
        static final String[] IMAGE_EXTENSION = { "gif", "jpg", "png" };
    
        private static final Banner DEFAULT_BANNER = new SpringBootBanner();
    

    如果我们在resources中指定了banner.txt或者图片类型的banner,那么就会从resources中加载,否则就会采用默认的SpringBootBanner

        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;
        }
    

    那么默认的SpringBootBanner就是我们常见的输出形式,我们看一下它的源码

    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();
        }
    
    }
    

    是不是很熟悉,当然,知道了原理,那么要修改它就很简单了,我们可以直接指定banner.txt,也可以指定ResourceBanner从我们希望的地方加载banner,比如直接从网络图片来加载

    public static void main(String[] args) {
            SpringApplication springApplication = new SpringApplication(DemoApplication.class);
            try {
                ImageBanner imageBanner = new ImageBanner(new UrlResource("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F201511%2F03%2F20151103192514_JMKza.thumb.400_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638846183&t=c62cdc650738467a80c637a5dc8a33e1"));
                springApplication.setBanner(imageBanner);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            springApplication.run(args);
        }
    

    启动效果如图


    image.png

    当然,也可以直接使用指定的字符串

    public static void main(String[] args) {
            SpringApplication springApplication = new SpringApplication(DemoApplication.class);
            try {
                String felix = "                                                                                                                       \n" +
                        "                                                                                                                       \n" +
                        "FFFFFFFFFFFFFFFFFFFFFF     EEEEEEEEEEEEEEEEEEEEEE     LLLLLLLLLLL                  IIIIIIIIII     XXXXXXX       XXXXXXX\n" +
                        "F::::::::::::::::::::F     E::::::::::::::::::::E     L:::::::::L                  I::::::::I     X:::::X       X:::::X\n" +
                        "F::::::::::::::::::::F     E::::::::::::::::::::E     L:::::::::L                  I::::::::I     X:::::X       X:::::X\n" +
                        "FF::::::FFFFFFFFF::::F     EE::::::EEEEEEEEE::::E     LL:::::::LL                  II::::::II     X::::::X     X::::::X\n" +
                        "  F:::::F       FFFFFF       E:::::E       EEEEEE       L:::::L                      I::::I       XXX:::::X   X:::::XXX\n" +
                        "  F:::::F                    E:::::E                    L:::::L                      I::::I          X:::::X X:::::X   \n" +
                        "  F::::::FFFFFFFFFF          E::::::EEEEEEEEEE          L:::::L                      I::::I           X:::::X:::::X    \n" +
                        "  F:::::::::::::::F          E:::::::::::::::E          L:::::L                      I::::I            X:::::::::X     \n" +
                        "  F:::::::::::::::F          E:::::::::::::::E          L:::::L                      I::::I            X:::::::::X     \n" +
                        "  F::::::FFFFFFFFFF          E::::::EEEEEEEEEE          L:::::L                      I::::I           X:::::X:::::X    \n" +
                        "  F:::::F                    E:::::E                    L:::::L                      I::::I          X:::::X X:::::X   \n" +
                        "  F:::::F                    E:::::E       EEEEEE       L:::::L         LLLLLL       I::::I       XXX:::::X   X:::::XXX\n" +
                        "FF:::::::FF                EE::::::EEEEEEEE:::::E     LL:::::::LLLLLLLLL:::::L     II::::::II     X::::::X     X::::::X\n" +
                        "F::::::::FF                E::::::::::::::::::::E     L::::::::::::::::::::::L     I::::::::I     X:::::X       X:::::X\n" +
                        "F::::::::FF                E::::::::::::::::::::E     L::::::::::::::::::::::L     I::::::::I     X:::::X       X:::::X\n" +
                        "FFFFFFFFFFF                EEEEEEEEEEEEEEEEEEEEEE     LLLLLLLLLLLLLLLLLLLLLLLL     IIIIIIIIII     XXXXXXX       XXXXXXX\n" +
                        "                                                                                                                       \n" +
                        "                                                                                                                       \n" +
                        "                                                                                                                       \n" +
                        "                                                                                                                       \n" +
                        "                                                                                                                       \n" +
                        "                                                                                                                       \n" +
                        "                                                                                                                       ";
    
                ResourceBanner resourceBanner = new ResourceBanner(new ByteArrayResource(felix.getBytes()));
                springApplication.setBanner(resourceBanner);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            springApplication.run(args);
        }
    

    执行效果如图

    image.png
    最后就是网上常见的方案了,直接放置一个banner.txt,然后SpringBoot启动之后就会自动加载了,这中方案网上很多,就不再介绍了。

    相关文章

      网友评论

          本文标题:手撕SpringBoot源码---启动时如何自定义Banner

          本文链接:https://www.haomeiwen.com/subject/ltfezltx.html