SpringBoot 入門篇(三) SpringApplication

一、SpringApplication的幾種常用方式

二、定制啟動Banner

三、SpringBoot事件和監聽器

四、SpringBoot的Web環境信息

五、SpringBoot的ApplicationRunner接口 和 CommandLineRunner接口

SpringBoot版本:1.5.13.RELEASE
對應官方文檔鏈接:https://docs.spring.io/spring-boot/docs/1.5.13.RELEASE/reference/htmlsingle/

上一篇:SpringBoot 入門篇(二) SpringBoot常用注解以及自動配置


一、SpringApplication的幾種常用方式

??在之前的兩篇SpringBoot 入門介紹中,都使用了在main方法中執行SpringApplication.run()這種方式來啟動我們的工程

// 方式一
@SpringBootApplication 
public class Application {

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

}

??如果我們需要在SpringBoot啟動過程中添加一些定制代碼(如定制啟動Banner,設置自定義監聽器等),這種方式就無法滿足我們的要求了,因此,官方文檔提供了其他的啟動方式來滿足我們定制需求。在給出官方文檔提供的啟動方式之前,我們進入SpringApplication.run()方法簡單看下底層做了些什么動作。

??可以看到,SpringApplication.run()的底層其實就是new了一個SpringApplication的對象,并執行run()方法,run()方法里面執行了哪些動作在之后的文章中詳細說明。接著我們來看官方文檔提供的啟動方式

// 方式二
public static void main(String[] args) {
    SpringApplication app = new SpringApplication(MySpringConfiguration.class);
    app.run(args);
}

到了這里,就不在多說什么了。
??有時我們需要創建多層次的ApplicationContext (例如,父子關系的Spring的ApplicationContext 和SpringMVC),這時我們可以使用官方提供的另外一種“平滑”的API調用方式來啟動工程,即使用SpringApplicationBuilder講多個方法調用串起來,通過parent() 和 child()來創建多層次的ApplicationContext。如果查看底層代碼,可以看到除了調用child()方法略有不同,其他的和前兩種方法幾乎一樣。

// 方式三
public static void main(String[] args) {
    new SpringApplicationBuilder()
        .sources(Parent.class)
        .child(Application.class)
        .run(args);
}

以上三方式是SpringBoot最常用的啟動方式,當然,官方還提供了通過配置application.properties文件在SpringBoot啟動過程中添加一些定制邏輯的方案。

二、定制啟動Banner

??如果在啟動時,打印的如下這個圖案(Banner)不符合我們的審美咋辦?如果我們要在圖案中加入公司標志或者版權聲明咋辦?如果我們不想打印Banner咋辦?

??SpringBoot為我們提供了修改Banner的方法。我們可以在類路徑下banner.txt、banner.gif、banner.jpg或者banner.png來定制Banner(banner.gif、banner.jpg或者banner.png會“翻譯”成對應的ASCII藝術圖案),當然,我們也可以在SpringBoot配置文件中指定banner.location或者banner.image.location對應的Banner路徑來定制Banner。
??需要注意的是,當文本文件(banner.txt)和圖像文件(banner.gif/jpg/png)是可以同時在控制臺顯示,但如果有多個圖像文件,只會顯示其中排序靠后的一個(即優先級png>jpg>gif)。

在banner.txt中還支持使用一些變量:
${spring-boot.version}:SpringBoot的版本
${spring-boot.formatted-version}:格式化后的SpringBoot的版本
${application.version}:應用版本(在MANIFEST.MF文件中定義)
${application.formatted-version}:格式化后的應用版本(在MANIFEST.MF文件中定義)
${application.title}:應用名稱(在MANIFEST.MF文件中定義)
${Ansi.NAME} (${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME}): ANSI控制碼

??如果我們通過代碼生成定制的Banner,那么可以自己實現Banner接口,通過實現printBanner()方法,并結合使用SpringApplication.setBanner(?)或者SpringApplicationBuilder.banner()的方式來打印定制的Banner。

??如果我們不想打印Banner,可以使用通過在代碼中設置Banner.Mode.OFF的方式關閉Banner打印。當然,也可以通過在配置文件中設置 spring.main.banner-mode=off 的方式進行關閉。

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        // 方式一
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);

         // 方式二
        /*new SpringApplicationBuilder()
                .sources(Application.class)
                .bannerMode(Banner.Mode.OFF)
                .run(args);*/
    }
}

三、SpringBoot事件和監聽器

??事件是用來通知監聽事件的監聽器某件事情的處理狀態,在SpringBoot啟動過程中,除了Spring框架的事件外,SpringBoot還會觸發其他的一些事件,這些事件按下列順序觸發:
(1)ApplicationStartingEvent:項目剛啟動時觸發,此時除了注冊監聽器和初始器之外,其他所有處理都沒有開始;
(2)ApplicationEnvironmentPreparedEvent:上下文得到環境信息之后觸發,此時上下文創建還沒有創建;
(3)ApplicationPreparedEvent:bean的定義信息加載完成之后觸發,此時bean還沒有初始化;
(4)ApplicationReadyEvent:在所有bean初始化完畢,所有回調處理完成,系統準備處理服務請求時觸發;
(5)ApplicationFailedEvent:啟動過程出現異常時候觸發。

??知道SpringBoot啟動時發送的時間后,我們就能自定義監聽器對這些事件進行監聽,從而達到擴展啟動流程的目的。我們的自定義監聽器需要實現ApplicationListener接口,同時指定需要監聽哪個事件。

??然后在main方法中,將自定義監聽器加入到SpringApplication中。

??除了上述代碼的方式添加監聽器外,還可以通過在classpath下創建META-INF/spring.factories文件,并將自定義監聽器通過鍵值對的形式(org.springframework.context.ApplicationListener = com.qzc.demo4.MyListener)加入到SpringApplication中。

??執行main方法啟動工程

四、SpringBoot的Web環境信息

??ApplicationContext是Spring框架中一個很重要的接口,它擴展了BeanFactory,增加了很多常用的功能。SpringBoot啟動過程中,SpringApplication通常會選擇合適的ApplicationContext實現類,在默認情況下,如果是Web應用,則會創建AnnotationConfigEmbeddedWebApplicationContext類的對象;否則會創建AnnotationConfigApplicationContext類的對象。
??通過查看SpringApplication,run()的底層代碼,可以看到,創建什么類型的ApplicationContext是由 webEnvironment 這個布爾變量來決定的,而 webEnvironment 這個變量是由項目的classpath下是否存在javax.servlet.Servlet或者org.springframework.web.context.ConfigurableWebApplicationContext,如果存在其中的一個,則為true;否則為false。

??我們可以通過SpringApplication.setWebEnvironment()方法來改變webEnvironment 變量從而改變ApplicationContext的具體類型。當然,我們還可以通過setApplicationContextClass()方法來完全定制ApplicationContext。

        SpringApplication application = new SpringApplication(Application.class);
        application.setWebEnvironment(false);
        // application.setApplicationContextClass(...);
        application.run(args);

五、SpringBoot的ApplicationRunner接口 和 CommandLineRunner接口

??如果我們想在SpringBoot啟動時傳入一些參數進行一些特殊的業務邏輯處理,此時我們可以去實現ApplicationRunner 或者 CommandLineRunner 接口,這兩個接口都只有一個run()方法,該run()方法會在SpringApplication.run(?) 完成之前被調用。另外,如果我們有多個類實現了ApplicationRunner 或者 CommandLineRunner 接口,我們可以在該類上標注@Order注解或者讓該類再實現org.springframework.core.Ordered接口來保證執行的順序。
??ApplicationRunner 和 CommandLineRunner 的區別就是封裝參數的形式不一樣,ApplicationRunner將參數封裝到ApplicationArguments類中,而CommandLineRunner 將參數傳到String可變數組中。

@Component
@Order(1) // 數值越小,優先級越高
public class MyCommandLineRunner implements CommandLineRunner {
//public class MyCommandLineRunner implements CommandLineRunner, Order {
    @Override
    public void run(String... args) {
        if (args != null) {
            for (String s : args) {
                System.out.println("MyCommandLineRunner:" + s);
            }
        }
    }

}
@Component
@Order(2) // 數值越小,優先級越高
public class MyApplicationRunner implements ApplicationRunner {
// public class MyApplicationRunner implements ApplicationRunner, Order {
    @Override
    public void run(ApplicationArguments args) {
        if (args != null) {
            String[] argArr = args.getSourceArgs();
            for (String s : argArr) {
                System.out.println("MyApplicationRunner:" + s);
            }
        }
    }
}
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.run(args);
    }

}

??在IDEA中進行如下配置

啟動執行main方法啟動工程可以看到


上一篇:SpringBoot 入門篇(二) SpringBoot常用注解以及自動配置
下一篇:SpringBoot 入門篇(四) SpringBoot外部配置以及優先級

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容